ng-model for <input type =“file”/>

我试图用types文件在input标签上使用ng-model:

<input type="file" ng-model="vm.uploadme" /> 

但是在select文件后,在控制器中,$ scope.vm.uploadme仍然是未定义的。

我如何获得我的控制器中选定的文件?

我用指令创build了一个解决方法:

 .directive("fileread", [function () { return { scope: { fileread: "=" }, link: function (scope, element, attributes) { element.bind("change", function (changeEvent) { var reader = new FileReader(); reader.onload = function (loadEvent) { scope.$apply(function () { scope.fileread = loadEvent.target.result; }); } reader.readAsDataURL(changeEvent.target.files[0]); }); } } }]); 

input标签变成:

 <input type="file" fileread="vm.uploadme" /> 

或者,如果只需要文件定义:

 .directive("fileread", [function () { return { scope: { fileread: "=" }, link: function (scope, element, attributes) { element.bind("change", function (changeEvent) { scope.$apply(function () { scope.fileread = changeEvent.target.files[0]; // or all selected files: // scope.fileread = changeEvent.target.files; }); }); } } }]); 

我使用这个指令:

 angular.module('appFilereader', []).directive('appFilereader', function($q) { var slice = Array.prototype.slice; return { restrict: 'A', require: '?ngModel', link: function(scope, element, attrs, ngModel) { if (!ngModel) return; ngModel.$render = function() {}; element.bind('change', function(e) { var element = e.target; $q.all(slice.call(element.files, 0).map(readFile)) .then(function(values) { if (element.multiple) ngModel.$setViewValue(values); else ngModel.$setViewValue(values.length ? values[0] : null); }); function readFile(file) { var deferred = $q.defer(); var reader = new FileReader(); reader.onload = function(e) { deferred.resolve(e.target.result); }; reader.onerror = function(e) { deferred.reject(e); }; reader.readAsDataURL(file); return deferred.promise; } }); //change } //link }; //return }); 

并像这样调用它:

 <input type="file" ng-model="editItem._attachments_uri.image" accept="image/*" app-filereader /> 

该属性(editItem.editItem._attachments_uri.image)将填充您select的文件的内容作为数据URI(!)。

请注意,这个脚本不会上传任何东西。 它只会填充您的模型文件的内容编码和数据uri(base64)。

看看这里的工作演示: http : //plnkr.co/CMiHKv2BEidM9SShm9Vv

这是@ endy-tjahjono解决scheme的附录。

我最终无法从范围中获得uploadme的价值。 即使HTML中的uploadme被指令明显更新,我仍然无法通过$ scope.uploadme访问它的值。 不过,我可以从范围中设定它的价值。 神秘,对..

事实certificate,子范围是由指令创build的,子范围有自己的uploadme

解决的办法是使用一个对象而不是一个基元来保存uploadme的值。

在控制器中我有:

 $scope.uploadme = {}; $scope.uploadme.src = ""; 

并在HTML中:

  <input type="file" fileread="uploadme.src"/> <input type="text" ng-model="uploadme.src"/> 

指令没有改变。

现在,这一切都像预期的那样工作。 我可以使用$ scope.uploadme从我的控制器中获取uploadme.src的值。

嗨,大家好,我创build了一个指令,并注册在凉亭。

这个库将帮助你build模input文件,不仅可以返回文件数据,还可以文件dataurl或base 64。

 { "lastModified": 1438583972000, "lastModifiedDate": "2015-08-03T06:39:32.000Z", "name": "gitignore_global.txt", "size": 236, "type": "text/plain", "data": "data:text/plain;base64,DQojaWdub3JlIHRodW1ibmFpbHMgY3JlYXRlZCBieSB3aW5kb3dz…xoDQoqLmJhaw0KKi5jYWNoZQ0KKi5pbGsNCioubG9nDQoqLmRsbA0KKi5saWINCiouc2JyDQo=" } 

https://github.com/mistralworks/ng-file-model/

希望会帮助你

使用ng-model的指令工作演示

该指令使<input type=file>能够自动处理ng-changeng-form指令。

 angular.module("app",[]); angular.module("app").directive("filesInput", function() { return { require: "ngModel", link: function postLink(scope,elem,attrs,ngModel) { elem.on("change", function(e) { var files = elem[0].files; ngModel.$setViewValue(files); }) } } }); 
 <script src="angular/angular.js"></script> <body ng-app="app"> <h1>AngularJS Input `type=file` Demo</h1> <input type="file" files-input ng-model="fileArray" multiple> <h2>Files</h2> <div ng-repeat="file in fileArray"> {{file.name}} </div> </body> 

这是一个稍微修改的版本,可以让你指定范围内的属性名称,就像你使用ng-model一样,用法:

  <myUpload key="file"></myUpload> 

指示:

 .directive('myUpload', function() { return { link: function postLink(scope, element, attrs) { element.find("input").bind("change", function(changeEvent) { var reader = new FileReader(); reader.onload = function(loadEvent) { scope.$apply(function() { scope[attrs.key] = loadEvent.target.result; }); } if (typeof(changeEvent.target.files[0]) === 'object') { reader.readAsDataURL(changeEvent.target.files[0]); }; }); }, controller: 'FileUploadCtrl', template: '<span class="btn btn-success fileinput-button">' + '<i class="glyphicon glyphicon-plus"></i>' + '<span>Replace Image</span>' + '<input type="file" accept="image/*" name="files[]" multiple="">' + '</span>', restrict: 'E' }; }); 

对于使用lodash或下划线input多个文件:

 .directive("fileread", [function () { return { scope: { fileread: "=" }, link: function (scope, element, attributes) { element.bind("change", function (changeEvent) { return _.map(changeEvent.target.files, function(file){ scope.fileread = []; var reader = new FileReader(); reader.onload = function (loadEvent) { scope.$apply(function () { scope.fileread.push(loadEvent.target.result); }); } reader.readAsDataURL(file); }); }); } } }]); 

我不得不在多个input上做同样的事情,所以我更新了@Endy Tjahjono方法。 它返回一个数组,其中包含所有获得的文件。

  .directive("fileread", function () { return { scope: { fileread: "=" }, link: function (scope, element, attributes) { element.bind("change", function (changeEvent) { var readers = [] , files = changeEvent.target.files , datas = [] ; for ( var i = 0 ; i < files.length ; i++ ) { readers[ i ] = new FileReader(); readers[ i ].onload = function (loadEvent) { datas.push( loadEvent.target.result ); if ( datas.length === files.length ){ scope.$apply(function () { scope.fileread = datas; }); } } readers[ i ].readAsDataURL( files[i] ); } }); } } }); 
 function filesModelDirective(){ return { controller: function($parse, $element, $attrs, $scope){ var exp = $parse($attrs.filesModel); $element.on('change', function(){ exp.assign($scope, this.files[0]); $scope.$apply(); }); } }; } app.directive('filesModel', filesModelDirective); 

我必须修改Endy的指令,这样我才能得到Last Modified,lastModifiedDate,name,size,type和data以及能够获取文件数组。 对于那些需要这些额外function的人,在这里你去。

更新:我发现了一个错误,如果你select文件,然后再次select,但取消,文件从来没有取消select,就像它出现。 所以我更新了我的代码来解决这个问题。

  .directive("fileread", function () { return { scope: { fileread: "=" }, link: function (scope, element, attributes) { element.bind("change", function (changeEvent) { var readers = [] , files = changeEvent.target.files , datas = [] ; if(!files.length){ scope.$apply(function () { scope.fileread = []; }); return; } for ( var i = 0 ; i < files.length ; i++ ) { readers[ i ] = new FileReader(); readers[ i ].index = i; readers[ i ].onload = function (loadEvent) { var index = loadEvent.target.index; datas.push({ lastModified: files[index].lastModified, lastModifiedDate: files[index].lastModifiedDate, name: files[index].name, size: files[index].size, type: files[index].type, data: loadEvent.target.result }); if ( datas.length === files.length ){ scope.$apply(function () { scope.fileread = datas; }); } }; readers[ i ].readAsDataURL( files[i] ); } }); } } });