Angular.js: 支持输入[类型=文件]绑定

创建于 2012-09-18  ·  145评论  ·  资料来源: angular/angular.js

嗨,尝试做一个简单的文件上传:) 但是 type=file 的输入似乎没有绑定我尝试过 hg-model-instant 但什么也没得到,甚至升级到 1.0.2 也没有

forms moderate not core feature

最有用的评论

此解决方案取决于正在实施的文件阅读器:

...
.directive('file', function() {
    return {
        restrict: 'E',
        template: '<input type="file" />',
        replace: true,
        require: 'ngModel',
        link: function(scope, element, attr, ctrl) {
            var listener = function() {
                scope.$apply(function() {
                    attr.multiple ? ctrl.$setViewValue(element[0].files) : ctrl.$setViewValue(element[0].files[0]);
                });
            }
            element.bind('change', listener);
        }
    }
});

<file name="image" ng-model="inputFile" accept="image/png,image/jpg,image/jpeg" />

然后你必须自己做一些 xhr 的事情,但我相信这超出了 gui 绑定和更多的处理逻辑。

如果你缺乏想象力:

var file = $scope.inputFile;
$http.put('http://localhost:5984/demo/d06917e8d1fae1ae162ea7773c003f0b/' + file.name + '?rev=4-c10029f35a5c5ed9bd8cc31bf8589d3c', file, { headers: { 'Content-Type' : file.type } });

这是因为 xhr2 (http://www.html5rocks.com/en/tutorials/file/xhr2) 并且请原谅长示例上传 url,它是一个 couchdb 文档端点(附件)。

所有145条评论

angular 没有为 input type=file 提供默认绑定。

但是,文件输入仅对 javascript 来说是真实的,这种绑定可以帮助的唯一好处是清除文件输入。 (我相信 Angular 现在也不提供对 ajax 文件上传的框架支持)

@coli :那不是全部真相。

能够在 input[file] 上捕获 onchange 事件是有意义的。

https://github.com/lgersman/jquery.orangevolt-ampere,我们有这样的场景:通过 XMLHTTPRequest V2 上传文件。
因此,我们实现了自己的指令来捕获 input[file] 更改事件,以便在不重新加载页面的情况下完成文件上传。

我很想在 angularjs 中看到这个功能!

绑定到类型文件的输入是否有任何进展? 我一直在寻找解决方案,但似乎找不到有效的解决方案...

我的解决方案只是 Ajax 而不是 request 或 http.post

从我的iPad发送

在2013年3月1日,在晚上7:16, “jgoldber”< [email protected] [email protected] >中写道:

绑定到类型文件的输入是否有任何进展? 我一直在寻找解决方案,但似乎找不到。


直接回复本邮件或在 Gi tHub上查看

我找到的最佳解决方案: http :

是的,这真的需要看看; 能够选择和上传文件对于大多数 Web 应用程序来说相当重要,因此支持此输入是一个非常明显的缺失功能。

撞。 这需要添加到里程碑。

另一个呼声支持这一点。

ng-model 文件可以将值设置为来自 HTML5 File API 的文件,IE8/IE9 有 Flash 和 Silverlight polyfills

是的,将值设置为文件或输入元素(包含对文件的引用)

此解决方案取决于正在实施的文件阅读器:

...
.directive('file', function() {
    return {
        restrict: 'E',
        template: '<input type="file" />',
        replace: true,
        require: 'ngModel',
        link: function(scope, element, attr, ctrl) {
            var listener = function() {
                scope.$apply(function() {
                    attr.multiple ? ctrl.$setViewValue(element[0].files) : ctrl.$setViewValue(element[0].files[0]);
                });
            }
            element.bind('change', listener);
        }
    }
});

<file name="image" ng-model="inputFile" accept="image/png,image/jpg,image/jpeg" />

然后你必须自己做一些 xhr 的事情,但我相信这超出了 gui 绑定和更多的处理逻辑。

如果你缺乏想象力:

var file = $scope.inputFile;
$http.put('http://localhost:5984/demo/d06917e8d1fae1ae162ea7773c003f0b/' + file.name + '?rev=4-c10029f35a5c5ed9bd8cc31bf8589d3c', file, { headers: { 'Content-Type' : file.type } });

这是因为 xhr2 (http://www.html5rocks.com/en/tutorials/file/xhr2) 并且请原谅长示例上传 url,它是一个 couchdb 文档端点(附件)。

通过结合这个基于 flash 的 FileReader Polyfill https://github.com/Jahdrien/FileReader和这个依赖 FileReader https://github.com/francois2metz/ 的纯 js FormData polyfill,可以在 IE8/9 中完成这项工作Moxie是一个更好的 polyfill

我的解决方案非常粗略,至少与上面的 jsfiddle 一样粗略,其中控制器原型被欺骗了......

在控制器中:

    $scope.updateImage = '(' + function () {
      alert('moo');
    }.toString() + ')();';

将我想要的 onchange 回调字符串化并将其包装在一个闭包中。

   <input type="file" name="image" onchange="{{updateImage}}" ng-model="image">

使用 Angular 将其插入 DOM

不是很漂亮,但它适用于 Webkit。 我没有做任何跨浏览器测试。

我在 1.0.5 上,它仍然坏了。 我们使用 Jgoldber 的示例并对其进行了一些调整:
http://jsfiddle.net/ADukg/2589/

此示例仅适用于一个控制器,因此如果您有多个控制器,每个控制器都有文件输入,则您需要进行一些更改。

还没有在 IE 上测试过它,但我的猜测(知道 IE)是它不会工作。

假设您只想在您的范围内调用一个将输入元素作为参数的函数,这在指令中实现起来非常简单:

http://jsfiddle.net/neilsarkar/vQzKJ/

(从上面的jsfiddle修改,感谢@programmist)

'use strict';

function filesModelDirective(){
  return {
    controller: function($parse, $element, $attrs, $scope){
      var exp = $parse($attrs.filesModel);

      $element.on('change', function(){
        exp.assign($scope, this.files);
        $scope.$apply();
      });
    }
  };
}

配置:

angular.module(...).directive('filesModel', filesModelDirective)

用法:

<input type="file" files-model="someObject.files" multiple>

请尽快解决这个问题。

仍然有问题.. 在某些版本中它可以工作,但无论如何不支持

从 1.5.0 开始,如果您使用 onchange 解决方法,则必须调用 $digest:

<input type="file" onchange="angular.element(this).scope().myController.uploadFile(this.files[0]); angular.element(this).scope().$digest();">

+1 更好地支持 ng-change 和输入/文件。 用例:作为图像的上传者,我希望能够在上传之前编辑该图像(调整大小和裁剪)以获得最佳显示效果。 实现:浏览到图像(使用输入/文件)并在 onchange 事件上将文件移动到画布并使用 fabricjs 进行编辑。 我想不出非变更实施。

cztomsik - 我在 1.0.7 上,我无法让你的解决方案工作 - scope(this) 函数解析正常,但找不到控制器,uploadFile 函数被列为 scope(this) 的成员。

胡说八道,我对这项技术略有修改,这似乎对我有用(我仍然不知道为什么我有:

< input type="file" name="file" ng-model="file" onchange="invokeUploadFile(this)"/ >

var invokeUploadFile = function(that) {
angular.element(that).scope().uploadFile(that)
angular.element(that).scope().$digest();
}

你能提供 jsfiddle/plunker 吗?
谢谢


    1. 2013 v 18:17,tb01923通知@github.com:

+1 更好地支持 ng-change 和输入/文件。 用例:作为图像的上传者,我希望能够在上传之前编辑该图像(调整大小和裁剪)以获得最佳显示效果。 实现:浏览到图像(使用输入/文件)并在 onchange 事件上将文件移动到画布并使用 fabricjs 进行编辑。 我想不出非变更实施。

cztomsik - 我在 1.0.7 上,我无法让你的解决方案工作 - scope(this) 函数解析得很好,但找不到控制器,uploadFile 函数被列为 scope(this) 对象的成员,但是当我删除我得到的控制器

未捕获的 ReferenceError:uploadFile 未定义 blah.js:15
$scope.uploadFile blah.js:15
invokeScope blah.js:4
变化中


直接回复此邮件或在 GitHub 上查看。

+1。 当用户选择一个文件时,需要它来启动 HTML5 文件上传。 这很容易解决,但我希望这能奏效。

+1。 请实施,不实施它完全不直观。

+1

+1

来吧伙计们......已经一年多了,angular 1.2.0 stil 没有输入文件绑定......我不明白为什么没有添加该功能? 已经有一些很好的实施方案。 我想要一个有角度的团队成员对这个问题的回应。

只是引用最好的解决方案之一(我知道这是一种数据绑定方式,但总比没有好,即使在 IE7 中,验证和模型更新也有效):

定义

  /**
   * <strong i="8">@ngdoc</strong> inputType
   * <strong i="9">@name</strong> angular.module.ng.$compileProvider.directive.input.file
   *
   * <strong i="10">@description</strong>
   * HTML file input field.
   *
   * <strong i="11">@param</strong> {string} ngModel Assignable angular expression to data-bind to.
   * <strong i="12">@param</strong> {string} multiple Allows multiple files selection.
   * <strong i="13">@param</strong> {string=} name Property name of the form under which the 
                                control is published.
   *
   * <strong i="14">@example</strong>
      <doc:example>
        <doc:source>
         <script>
           function Ctrl($scope) {
           }
         </script>
         <form name="myForm" ng-controller="Ctrl">
           file: <input type="file" ng-model="file"> single file selection.<br/>
           files: <input type="file" ng-model="files" multiple> multi-file selection.<br/>
           <tt>file.name = {{file.name}}</tt><br/>
           <tt>files.length = {{files.length}}</tt><br/>
          </form>
        </doc:source>
        <doc:scenario>
          it('should change state', function() {
            expect(binding('file.name')).toBeUndefined();

            input('file').select('a file name');
            expect(binding('file.name')).toEqual('a file name');
          });
        </doc:scenario>
      </doc:example>
   */
  'file': fileInputType,

功能

function fileInputType(scope, element, attr, ctrl) {
  element.bind('change', function() {
    scope.$apply(function() {
      var files = element[0].files,
          isValid = true;

      if (msie < 10) {
        files = [element[0].value];
      }

      if (attr.accept) {
        var i, j, acceptType, fileType,
            types = map(attr.accept.split(','), function(t) { return trim(t).split('/'); });
        for (i = 0; i < files.length && isValid; ++i) {
          fileType = files[i].type.split('/');
          isValid = false;
          for (j = 0; j < types.length && !isValid; ++j) {
            acceptType = types[j];
            isValid = acceptType[0] === fileType[0] && (acceptType[1] === '*' || acceptType[1] === fileType[1]);
          }
        }
      }
      ctrl.$setValidity('file', isValid);

      var viewValue;
      if (isValid) viewValue = attr.multiple ? files : files[0];
      ctrl.$setViewValue(viewValue);
    });
  });
}

+1

+1

@ntrp你为什么不公关这个变化?

该更改需要详细说明并进行测试,我目前没有时间这样做。

+1

+1

-1:巨魔脸:

开玩笑+1

+1

+1

+1

+1

+1

input[type=file] 并不是真正的 2 路绑定,除非我们明确使用 File API,它并非在所有目标浏览器上都可用。 将此添加到 ng-model 没有多大意义,但是有很多插件支持此功能的某些变体。 我们不能将其委托给插件一段时间吗?

http://caniuse.com/fileapi

@caitp是的,但是能够通过 ng-change 绑定到更改事件确实有意义,但它不起作用。

另一件事不起作用是表单验证。 我认为应该为新浏览器实现文件支持,并为旧浏览器提供单向数据绑定回退。 如果这个解决方案不可行,那么在我看来,应该在 wiki 上清楚地说明为什么没有实现该功能以及如何解决这种缺乏支持导致的问题。 我记得当我第一次使用它们时,在解决我的输入文件需求之前浪费了很多时间。

问题是,文件名不绑定到模型,将它们绑定到模型实际上没有意义。 File接口的每个属性都是只读的,而FileList接口只是Files的一个集合。 没有 2 路绑定的能力,所以首先没有真正的理由使用 ng-model。 改为绑定到change事件非常简单,您可以轻松编写指令来添加该功能,以便您可以在需要时以声明方式使用它。

但是,当它没有能力遵循 ng-model 行为时,将其作为 ng-model 的一部分有什么意义呢?

没有理由不能为文件创建自定义界面,angular 可能会在某些时候这样做,但在我看来它对 ng-model 没有意义。 我不知道其他开发人员对此有何看法,他们可能同意也可能不同意。 但从我的角度来看,单独的指令会更有意义,因为 input[type=file] 只是不适合 ng-model

  • 文件输入的值不能从脚本上下文中写入
  • 如果没有 File API(这在几个目标浏览器中不受支持),我们没有真正的方法来执行验证,本质上是浏览器为我们做的。 --- 除了 ngRequired 验证

我们真正可以为 input[type=file] 做的唯一一件事是 $setViewValue 当值发生变化时(这实际上没有意义),并以某种方式更改 ngModel 以忽略由脚本更改引起的模型值更改(或基本上只需完全禁用 $watch )。 至于验证,我们真正能支持的只是 ng-required,我的意思是我们还能做什么?

我也希望能够支持 ngModel 的文件输入,但我不知道它是如何工作的,它只是不适合 ngModel 接口。

我同意这个说法,但正如我之前所说,我们需要在 wiki 或一般文档中更加强调这一点,以便开发人员知道他们需要做什么才能实现他们需要的功能。

@ntrp well docs 补丁非常受欢迎,如果您提交一个,我很乐意查看:)

可以在 angular 本身中添加特定指令是一种解决方案吗?

我同意前面的说法,但看起来至少有点奇怪
像 angular 这样的框架没有清晰干净的方式来实现
这个...
这可能是我在尝试时不得不面对的最迷茫的事情
上传一个文件...

好吧@caitp ,我前段时间读到

我没有意识到 ngChange 指令也需要 ngModel 存在,我想这就是为什么这里有这么多关于 ngModel 的讨论(这就是为什么我得到这个错误)。 我同意 input[type=file] 上的 2 向绑定没有意义。

但是 ngChange 需要 ngModel 的确切原因是什么? 在我看来,能够绑定到 input[type=file] 字段的更改事件是完全有意义的,例如,如果您想在选择文件后自动提交表单。 在这种情况下,我并不真正关心该字段的值是什么。 我只关心它变了。 我发现处理这种事情的最好方法是通过@cztomsik上面提到的解决方法:

onchange="angular.element(this).scope().fileChangedHandler()"

这并不是最好的解决方案。

ng-change尽管名称与其他事件处理程序指令类似,但实际上并不是change事件的处理程序。 它只是在 ngModelController 中添加了一个$viewChangeListener ,每当$setViewValue被调用时就会被触发。

我同意这是一个不幸的名字

这是#1236 的骗局,已被此评论关闭: https :

除非我们看到有关如何实现这一点的提案,以便它既轻巧又实用,并且不需要将 ux 样式强加给 framewok 用户,否则我们会考虑它。 但是现在,我们认为文件上传问题足够复杂,可以作为一个独立的模块来解决,可能在核心之外。

+1

@IgorMinar看看这里,有点脏,但非常有趣的实现示例: https : @danialfarid在这方面取得了很大进展。

检查它是如何成为所有人的问题,几个问题打开了几个评论。 您必须为我们提供一个 ngUpload 模块: smile:。 也许您可以提供 html5 实现并将使用示例与https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills#file -api 附加到http://docs.angularjs.org/guide /IE。

你想怎么解决?

+1

+1

+1

+1

+1

+1

+1

+1

哇,这个阶段有点尴尬。

+1

对文件输入进行 2 向绑定是不可能的,当然,当目标浏览器并不都支持文件 API (http://caniuse.com/fileapi) 时——但即使可以, input[type=file]无论如何都不太适合。 2路绑定真的是不可能的

对不起,这更像是网络平台的问题/安全功能,而不是其他任何东西。 如果可行,就会完成

@caitp我完全明白你在说什么,但“这更像是网络平台的问题/安全功能,而不是其他任何东西”是一个有点荒谬的说法。 框架的目的是为了弥补浏览器、网络规范和各种不一致的缺点。 这当然是对 fileAPI 进行警告的地方。 现在有解决方案,为什么不把它们折叠起来?

例如,像包装器这样简单的东西就是一个开始。

考虑到 Angular 2.0 的发展方向(转译仅限 Angular 的非 ECMA 习语),我认为“网络平台”的局限性不应该成为问题。

@everyone else: Ember 在这种情况下做什么?

编辑:从转译语句中删除“必需”。

_只是快速澄清一下。_ 构建 Angular 2.0 应用程序不需要转译语言或非 ECMA 习语。 你可以使用普通的 ES5 代码就好了。 如果要构建 Angular 2.0 源代码,则需要使用 traceur 进行编译。 当然,您可以使用 traceur 构建自己的应用程序并利用我们在 Angular 中使用的相同功能,但这完全是可选的。 抱歉,如果我们的公告中在这一点上有一些混淆。

@EisenbergEffect我不好。 我知道这一点,应该更好地校对。 没有咖啡!

框架无法真正绕过 Web 平台的限制。 比如,我们不能强制浏览器让我们写入只读 IDL 属性(这确实打破了文件的 2 向绑定),我们也不能强制浏览器向我们公开文件系统,这确实阻止了我们这样做任何有趣的东西

@caitp我关注这个问题已经有一段时间了。 我认为似乎有足够的社区希望 Angular 支持简单的文件选择输入。 目前(除非我弄错了),构建一个接受文件并使用 Angular 通过 XHR 上传它的简单应用程序没有推荐的模式可遵循? 这听起来像是一个至少值得关注的功能,除了“抱歉不能这样做,因为双向绑定在这里没有意义。”

也许我们可以将这个对话重新定位为“角度如何支持这个?” 而不是“它不适合我们当前的模式。”

绑定到文件输入绝对是可能的,事实上我已经在以前的 AngularJS 项目中完成了它。

您不能与文件输入进行双向绑定这一事实是一项安全功能,这是有道理的。 作者永远无法通过脚本设置文件路径,但为什么不只是单向绑定呢?

当然它打破了范式,但谁真的在乎这是否意味着您可以获得 ng-change 和通过文件 API 访问文件的能力而无需黑客攻击? jQuery 可以绑定到文件输入的更改事件,Angular 的方式是否如此神圣以至于我们不能将它绑定到控制器中? 是架构的技术限制还是意识形态的障碍?

同意,我不太关心 2 路绑定。 我只是想将文件与我的文档的其余部分一起发布,而不是跳过箍。

在2014年5月20日,在上午07时53分,贾斯汀阿鲁达< [email protected] [email protected] >中写道:

@c aitphttps://github.com/caitp我关注这个问题已经有一段时间了。 我认为似乎有足够的社区希望 Angular 支持简单的文件选择输入。 目前(除非我弄错了),构建一个接受文件并使用 Angular 通过 XHR 上传它的简单应用程序没有可遵循的官方模式? 除了“抱歉不能这样做,因为双向绑定在这里没有意义”之外,这听起来是不是一个至少值得关注的功能。

也许我们可以将这个对话重新定位为“角度如何支持这个?” 而不是“它不适合我们当前的模式。”


直接回复本邮件或在 Gi tHub上查看

然后你有一种情况,其中 ng-model 对于一个特定的表单控件表现得非常不同,然后你有人提交错误,比如“当我将值更改为“foobarblah.txt”或其他任何内容时,表单控件如何发送错误的文件。不一致的 API -> 不好。

ngModel 并不完全适合这些东西,特别是因为它意味着我们有一个特定的模式可以适应,并且应用程序作者很难关闭。 不过,angular.dart 和 v2.0.0 原型中有解决方案,因此将来会更好。 但是我们真的不能添加另一个忽略 ng-model 当前所做的一切的 ng-model 行为,这是没有意义的

接受一个文件并使用 Angular 通过 XHR 上传它

@guruward我们不能在 1.x 的所有目标浏览器上都支持这一点,而不强迫人们使用冲击波 polyfills 或类似的东西。 有第三方模块允许这样做,并且可以使用它们。 angular-file-upload 同时提供了冲击波 polyfill 和 html5 原生版本,并选择了正确的一个。 所以这不是一个糟糕的解决方案,如果你想这样做,强烈推荐。

但是我不确定我们是否可以将其放入核心中,您必须询问 Igor 他对在核心中运送冲击波 polyfill 的看法。

我并不是说这是一个人们永远不想做的用例,我可以理解想要这样做,我只是说它不适合 ngModel 模式,并且需要我们添加一些额外的 cruft 以便支持所有目标浏览器,因此它以这种方式破坏了框架。

为此使用第三方模块有什么危害?

这个 polyfill不需要 flash。

@jreading这不是一个

它所做的是依赖于 File API,该 API 并非在所有目标浏览器中都可用,因此对于 angular 1.x 核心来说是有问题的。

没有那个 API,你就无法在没有冲击波之类的东西的情况下获取文件 blob。

它使用 iframes 而不是 flash,你可能会想到这个。 与其争论语义,不如来一份路线图? 让我们从支持文件 API 的浏览器的文件输入的 ng-change 开始。

@jreading不幸的是,这对不支持 api 的浏览器没有帮助,其中包括仍受支持的 IE9。 我们无法发布在支持的浏览器 A 上运行但在核心中不支持浏览器 B 的 API,而对依赖 IE9 支持的人没有任何解决办法。 不,iframe 不会将文件的内容公开为 blob 并使其可上传。 哼哼。

第三方模块中有针对此的解决方案,如果应用程序觉得合适,可以使用这些模块。 把它放在核心 A) 会给那些第三方模块带来困难,而 B) 无法支持所有目标浏览器,所以这是一个问题。

这只是我的意见,也许 Igor 或其他人会不同意,但我认为这不是正确的方法。

如果第三方模块对您有用并且您需要它们,那么使用它们有什么危害?

从来没有真正暗示控制器需要可以使用 blob。 我正在冒险,但我看到的最大用例是能够知道文件输入何时发生更改以及将其发送到休息端点的能力,这在此 iframe 解决方案或文件 API 和 angular 中可用黑客。

3rd 方模块是唯一的方法,或者像我的博客文章那样进行积极的增强(不给你上传!!),但我可以转过头来问“为现代浏览器提供更好的 api 有什么危害?”

“为现代浏览器提供更好的 api 有什么害处?”

这个论点很弱,因为它没有考虑机会成本; 我们(核心团队)还有很多其他事情要做。

很公平。 感觉就像一个巨大的差距和悬而未决的果实。

这里的问题不在于如何使用 ngModel 使其工作。 我认为 ngModel 可以将 FileList 从输入字段公开到作用域,但在另一个方向,我们只允许将模型设置为 null/undefined 以支持。 解析器/格式化器可能不会做任何事情,验证器只会做一些简单的事情,比如检查文件是否存在。

问题是(如前所述)如果没有文件 api 支持,正确地执行此操作对于核心是不可行的,因为我们的基线是 IE9,并且对于核心来说,polyfilling 这些东西是不可能的。

此外,尝试以不跨浏览器兼容的方式处理此输入只会使 3rd 方解决方案变得更加困难,现在必须与核心解决方案作斗争/禁用/解决。

已经存在处理此问题的非核心解决方案,并且在本期讨论以及上一期中都提到了它们

还有许多其他影响更大的事情我们想要完成。 我知道这是一个比较常见的情况,但我仍然没有听说为什么现有的解决方案不够用?

如果他们需要的话,是否可以将一些投入到讨论中的精力重新用于改进现有解决方案,或者创建一个优于现有解决方案的新解决方案?

就像我们关闭 #1236 一样,我将关闭它。 Angular 2 正在构建以支持现代浏览器,并且可以轻松获得文件支持。

我只想知道更改事件何时发生,以便我可以直接访问元素并获取文件信息并通过 AJAJ 上传。

@bjoshuanoah那么你需要 ngModel 做什么? 只需将事件侦听器绑定到输入 =p

@caitp我想控制控制器中的所有内容,而不是使用指令。

如果我把 ng-change="uploadFile({$event: $event})"

我可以在我的控制器中有 $scope.uploadFile(event) 。 并在那里处理。

我的具体用例是:将文件上传到 s3,将 url 应用于我的模型。

相反,我必须闯入范围来做同样的事情。 很烦人:

<input name="highRes" scope="{{contentOptions.currentValue}}" key="value" type="file" onchange="angular.element(this).scope().setFile(this)">

我希望有人能解决这个问题。 所以我们都可以继续前进:)

2014 年 7 月 25 日上午 9:22,Brian < [email protected] [email protected] > 写道:

我只想知道更改事件何时发生,以便我可以直接访问元素并获取文件信息并通过 AJAJ 上传。


直接回复本邮件或在 Gi tHub上查看

+1

+1

+1000000000000000

+1

+1

+1

+1

+100500

+1
我不确定为什么 Ajax 是一个问题。 人们可能希望将数据从本地机器上的 csv 文件加载到 Angular 模型中。 如果 ng-change 在 Angular 中的文件输入中工作,这将很容易,目前它不是. 此场景根本不需要 Ajax 或服务器 API。 我也不确定为什么这是关闭的?

我目前的解决方法是执行以下操作

 input(type="file", onchange="angular.element(this).scope().onFileSet(this.files)")

在我的控制器中有类似的东西

$scope.onFileSet = function(files) { 
// work your magic here 
}

非常糟糕,我觉得我把 angular 作为一种工具混为一谈。 任何有关如何以更有角度的方式执行此操作的见解将不胜感激。

:心: :心:

这是一艘帆船: :sailboat:

@samccone调试模式关闭时 scope() 不可用吗?

@geetsce这是正确的(在 1.3.x 及更高版本中)

好吧,在1.2土地上一切都很好。

@Narrez你有更好的解决方案吗?

这对我有用,它的灵感来自https://jasonturim.wordpress.com/2013/09/01/angularjs-drag-and-drop

<input type="file" multiple="multiple" data-dbinf-on-files-selected="chooseAFunctionName(selectedFileList)">
<script>
/**Directive to propagate selected files from an HTML input element with type="file"
 * to the surrounding AngularJS controller.
 */
myApp.directive('dbinfOnFilesSelected', [function() {
    return {
        restrict: 'A',
        scope: {
              //attribute data-dbinf-on-files-selected (normalized to dbinfOnFilesSelected) identifies the action
              //to take when file(s) are selected. The '&' says to  execute the expression for attribute
              //data-dbinf-on-files-selected in the context of the parent scope. Note though that this '&'
              //concerns visibility of the properties and functions of the parent scope, it does not
              //fire the parent scope's $digest (dirty checking): use $scope.$apply() to update views
              //(calling scope.$apply() here in the directive had no visible effect for me).
            dbinfOnFilesSelected: '&'
        },
        link: function(scope, element, attr, ctrl) {
            element.bind("change", function()
            {  //match the selected files to the name 'selectedFileList', and
               //execute the code in the data-dbinf-on-files-selected attribute
             scope.dbinfOnFilesSelected({selectedFileList : element[0].files});
            });
        }
    }
}]);

myApp.controller('myController', ['$scope', function($scope) {
    $scope.chooseAFunctionName = function (filelist) {
        for (var i = 0; i < filelist.length; ++i) {
            var file = filelist.item(i);
            //do something with file; remember to call $scope.$apply() to trigger $digest (dirty checking)
            alert(file.name);
           }
    };
}]);
</script>

+1

+1

不会发生的……放手吧,放手吧……

+1

正如@samccone所说,

input(type="file", onchange="angular.element(this).scope().onFileSet(this.files)")

这不是 Angular 的做事方式。 这很奇怪。

+1

+1

+1

@caitp @Narretz,如果你们希望我可以为此为 1.2x 分支制定 PR,请告诉我您是否要添加此内容。 我理解安全问题和缺乏跨浏览器支持就获得对实际文件对象的访问而言,但是似乎对检测文件输入何时更改(传入原始事件)的基本支持将提供足够的钩子让人们发挥他们的魔力。

再次感谢你所做的一切 :palm_tree:

+1

+1

+1

+1

+1

ng-file-upload运行良好。

+1 @neokyol !! 它确实很好用!

默认情况下,此通用功能必须在框架中

有帮助的

+1

+1

+1

+1

+1

这对我有用,可能会有所帮助

angular.module('app', [])
  .controller('MainCtrl', MainCtrl)
  .directive('fileChange', fileChange);

  function MainCtrl($scope) {
    $scope.upload = function () {
      // do something with the file
      alert($scope.file.name);
    };
  }

  function fileChange() {
    return {
      restrict: 'A',
      require: 'ngModel',
      scope: {
        fileChange: '&'
      },
      link: function link(scope, element, attrs, ctrl) {
        element.on('change', onChange);

        scope.$on('destroy', function () {
          element.off('change', onChange);
        });

        function onChange() {
          ctrl.$setViewValue(element[0].files[0]);
          scope.fileChange();
        }
      }
    };
  }
<div ng-app="app" ng-controller="MainCtrl">
  <input type="file" file-change="upload()" ng-model="file">
</div>

http://plnkr.co/edit/JYX3Pcq18gH3ol5XSizw?p=preview

+1

+1

+1

+1

+1000000000000000000000000

+1

+1

@dciccale能否请您提供plunker 示例。

+1

+1

+1 为此,核心库中应该有一个内置指令。 很可笑

+1

+1
该功能是否计划用于下一个版本?

+1

+1

在 $scope 永远不会被注入控制器的项目中如何做到这一点。 我正在使用 laravel angular,它使用 GULP 和 ES6 声明控制器的方式。

IE

class TestController{
    constructor(API){
        'ngInject';
        this.API = API
    }

    $onInit(){
        this.file = null;
    }
    upload() {
        console.log(this.file)
    }
    fileChanged(elm) {
        console.log('hey')
        this.file = elm.file;
        this.$apply();
    }
}

export const TestComponent = {
    templateUrl: './views/app/components/test/test.component.html',
    controller: TestController,
    controllerAs: 'vm',
    bindings: {}
}

我找到了一个我相信的工作。 http://stackoverflow.com/questions/38449126/how-to-set-up-ng-file-upload-in-laravel-angular-project/38486379#38486379

+1

@ntrp @guruward @coli @lgersman @jgoldber @Siyfion
你是如何修复验证的
我的验证:
this.catalougeForm = this.catalougeFormBuilder.group({
目录图标名称:['',Validators.required]
});
网址:
(change)="changeListener($event)">

我的验证器在我上传后将 catalougeIconName 值视为空/空。
正在发送图像,但验证器不起作用

有任何更新吗?

任何更新 ?

此页面是否有帮助?
0 / 5 - 0 等级