AngularJs:如何检查文件输入字段中的更改?

我是新角度。 我试图从HTML'文件'字段读取上传的文件路径,每当这个领域发生'改变'。 如果我使用'onChange'它可以工作,但是当我使用'ng-change'角度的方式它不起作用。

<script> var DemoModule = angular.module("Demo",[]); DemoModule .controller("form-cntlr",function($scope){ $scope.selectFile = function() { $("#file").click(); } $scope.fileNameChaged = function() { alert("select file"); } }); </script> <div ng-controller="form-cntlr"> <form> <button ng-click="selectFile()">Upload Your File</button> <input type="file" style="display:none" id="file" name='file' ng-Change="fileNameChaged()"/> </form> </div> 

fileNameChaged()永远不会调用。 Firebug也不会显示任何错误。

没有文件上传控件的绑定支持

https://github.com/angular/angular.js/issues/1375

 <div ng-controller="form-cntlr"> <form> <button ng-click="selectFile()">Upload Your File</button> <input type="file" style="display:none" id="file" name='file' onchange="angular.element(this).scope().fileNameChanged(this)" /> </form> </div> 

代替

  <input type="file" style="display:none" id="file" name='file' ng-Change="fileNameChanged()" /> 

你可以试试

 <input type="file" style="display:none" id="file" name='file' onchange="angular.element(this).scope().fileNameChanged()" /> 

注意:这要求角度应用程序始终处于调试模式 。 如果禁用调试模式,这将无法在生产代码中使用。

并在你的功能改变,而不是

 $scope.fileNameChanged = function() { alert("select file"); } 

你可以试试

 $scope.fileNameChanged = function() { console.log("select file"); } 

以下是拖放文件上传的文件上传的一个工作示例可能是有帮助的http://jsfiddle.net/danielzen/utp7j/

有角度的文件上传信息

在ASP.Net中的AngularJS文件上传的URL

http://cgeers.com/2013/05/03/angularjs-file-upload/

AngularJs本地多文件上传与NodeJS的进展

http://jasonturim.wordpress.com/2013/09/12/angularjs-native-multi-file-upload-with-progress/

ngUpload – 一个AngularJS服务,用于使用iframe上传文件

http://ngmodules.org/modules/ngUpload

我做了一个小的指令来侦听文件输入的变化。

查看JSFiddle

view.html:

 <input type="file" custom-on-change="uploadFile"> 

controller.js:

 app.controller('myCtrl', function($scope){ $scope.uploadFile = function(event){ var files = event.target.files; }; }); 

directive.js:

 app.directive('customOnChange', function() { return { restrict: 'A', link: function (scope, element, attrs) { var onChangeHandler = scope.$eval(attrs.customOnChange); element.bind('change', onChangeHandler); element.on('$destroy', function() { element.unbind('change'); }); } }; }); 

这是一些其他的改进,数据将以ng-model结尾,这通常是你想要的。

标记(只需创建一个属性数据文件,以便指令可以找到它)

 <input data-file id="id_image" name="image" ng-model="my_image_model" type="file"> 

JS

 app.directive('file', function() { return { require:"ngModel", restrict: 'A', link: function($scope, el, attrs, ngModel){ el.bind('change', function(event){ var files = event.target.files; var file = files[0]; ngModel.$setViewValue(file); $scope.$apply(); }); } }; }); 

干净的方法是写你自己的指令绑定到“更改”事件。 只是为了让你知道IE9不支持FormData,所以你不能真正从变化事件中获取文件对象。

您可以使用已经支持IE的ng-file-upload库和FileAPI polyfill,并简化将文件发布到服务器。 它使用一个指令来实现这一点。

 <script src="angular.min.js"></script> <script src="ng-file-upload.js"></script> <div ng-controller="MyCtrl"> <input type="file" ngf-select="onFileSelect($files)" multiple> </div> 

JS:

 //inject angular file upload directive. angular.module('myApp', ['ngFileUpload']); var MyCtrl = [ '$scope', 'Upload', function($scope, Upload) { $scope.onFileSelect = function($files) { //$files: an array of files selected, each file has name, size, and type. for (var i = 0; i < $files.length; i++) { var $file = $files[i]; Upload.upload({ url: 'my/upload/url', data: {file: $file} }).then(function(data, status, headers, config) { // file is uploaded successfully console.log(data); }); } } }]; 

我已经扩展了@Stuart Axon的想法,为文件输入添加双向绑定(即允许通过将模型值重置为空来重置输入):

 app.directive('bindFile', [function () { return { require: "ngModel", restrict: 'A', link: function ($scope, el, attrs, ngModel) { el.bind('change', function (event) { ngModel.$setViewValue(event.target.files[0]); $scope.$apply(); }); $scope.$watch(function () { return ngModel.$viewValue; }, function (value) { if (!value) { el.val(""); } }); } }; }]); 

演示

类似于其他的一些好的答案,我写了一个指令来解决这个问题,但是这个实现更加贴近事件的角度。

你可以像这样使用指令:

HTML

 <input type="file" file-change="yourHandler($event, files)" /> 

正如你所看到的,你可以将选中的文件注入到你的事件处理程序中,就像在任何ng事件处理程序中注入一个$ event对象一样。

使用Javascript

 angular .module('yourModule') .directive('fileChange', ['$parse', function($parse) { return { require: 'ngModel', restrict: 'A', link: function ($scope, element, attrs, ngModel) { // Get the function provided in the file-change attribute. // Note the attribute has become an angular expression, // which is what we are parsing. The provided handler is // wrapped up in an outer function (attrHandler) - we'll // call the provided event handler inside the handler() // function below. var attrHandler = $parse(attrs['fileChange']); // This is a wrapper handler which will be attached to the // HTML change event. var handler = function (e) { $scope.$apply(function () { // Execute the provided handler in the directive's scope. // The files variable will be available for consumption // by the event handler. attrHandler($scope, { $event: e, files: e.target.files }); }); }; // Attach the handler to the HTML change event element[0].addEventListener('change', handler, false); } }; }]); 

该指令也传递选定的文件:

 /** *File Input - custom call when the file has changed */ .directive('onFileChange', function() { return { restrict: 'A', link: function (scope, element, attrs) { var onChangeHandler = scope.$eval(attrs.onFileChange); element.bind('change', function() { scope.$apply(function() { var files = element[0].files; if (files) { onChangeHandler(files); } }); }); } }; }); 

HTML,如何使用它:

 <input type="file" ng-model="file" on-file-change="onFilesSelected"> 

在我的控制器中:

 $scope.onFilesSelected = function(files) { console.log("files - " + files); }; 

我建议创建一个指令

 <input type="file" custom-on-change handler="functionToBeCalled(params)"> app.directive('customOnChange', [function() { 'use strict'; return { restrict: "A", scope: { handler: '&' }, link: function(scope, element){ element.change(function(event){ scope.$apply(function(){ var params = {event: event, el: element}; scope.handler({params: params}); }); }); } }; }]); 

这个指令可以多次使用,它使用自己的作用域,不依赖于父作用域。 你也可以给处理函数一些参数。 处理函数将被调用范围对象,当您更改输入时,该对象是活动的。 每次调用change事件时,$都会应用更新模型

最简单的Angular jqLit​​e版本。

JS:

 .directive('cOnChange', function() { 'use strict'; return { restrict: "A", scope : { cOnChange: '&' }, link: function (scope, element) { element.on('change', function () { scope.cOnChange(); }); } }; }); 

HTML:

 <input type="file" data-c-on-change="your.functionName()"> 

太完整的解决方案基于:

 `onchange="angular.element(this).scope().UpLoadFile(this.files)"` 

一个简单的方法来隐藏输入字段并将其替换为图像,这里解决方案之后,这也需要一个角度的黑客,但做这项工作[TriggerEvent不按预期工作]

解决方案:

  • 将输入字段放在显示中:无[输入字段存在于DOM中但不可见]
  • 将图像放在图像后使用nb-click()激活一个方法

当图像被点击时,在输入栏中模拟一个DOM动作“点击”。 Etvoilà!

  var tmpl = '<input type="file" id="{{name}}-filein"' + 'onchange="angular.element(this).scope().UpLoadFile(this.files)"' + ' multiple accept="{{mime}}/*" style="display:none" placeholder="{{placeholder}}">'+ ' <img id="{{name}}-img" src="{{icon}}" ng-click="clicked()">' + ''; // Image was clicked let's simulate an input (file) click scope.inputElem = elem.find('input'); // find input in directive scope.clicked = function () { console.log ('Image clicked'); scope.inputElem[0].click(); // Warning Angular TriggerEvent does not work!!! }; 

我是这样做的;

 <!-- HTML --> <button id="uploadFileButton" class="btn btn-info" ng-click="vm.upload()"> <span class="fa fa-paperclip"></span></button> <input type="file" id="txtUploadFile" name="fileInput" style="display: none;" /> 
 // self is the instance of $scope or this self.upload = function () { var ctrl = angular.element("#txtUploadFile"); ctrl.on('change', fileNameChanged); ctrl.click(); } function fileNameChanged(e) { console.log(self.currentItem); alert("select file"); } 

监听文件输入更改的另一个有趣方法是监视输入文件的ng-model属性。 当然FileModel是一个自定义指令。

喜欢这个:

HTML – > <input type="file" file-model="change.fnEvidence">

JS代码 – >

 $scope.$watch('change.fnEvidence', function() { alert("has changed"); }); 

希望它可以帮助别人。

ng-change一起使用的“files-input”指令的工作演示1

为了使<input type=file>元素能够工作在ng-change指令中,它需要一个自定义指令来处理ng-model指令。

 <input type="file" files-input ng-model="fileList" ng-change="onInputChange()" multiple /> 

演示

 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); }) } } }) .controller("ctrl", function($scope) { $scope.onInputChange = function() { console.log("input change"); }; }) 
 <script src="//unpkg.com/angular/angular.js"></script> <body ng-app="app" ng-controller="ctrl"> <h1>AngularJS Input `type=file` Demo</h1> <input type="file" files-input ng-model="fileList" ng-change="onInputChange()" multiple /> <h2>Files</h2> <div ng-repeat="file in fileList"> {{file.name}} </div> </body> 

角元素(如指令的根元素)是jQuery [Lite]对象。 这意味着我们可以像这样注册事件监听器:

 link($scope, $el) { const fileInputSelector = '.my-file-input' function setFile() { // access file via $el.find(fileInputSelector).get(0).files[0] } $el.on('change', fileInputSelector, setFile) } 

这是jQuery事件委托。 在这里,监听器被附加到指令的根元素。 当事件触发时,它会冒泡到注册的元素,jQuery将确定事件是否发生在与定义的选择器匹配的内部元素上。 如果是这样,处理程序将会启动。

这种方法的好处是:

  • 处理程序绑定到$元素,当指令作用域被销毁时,元素将被自动清理。
  • 模板中没有代码
  • 即使在注册事件处理程序时(如使用ng-ifng-switch )目标代理(输入)尚未呈现,

http://api.jquery.com/on/