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上传文件
我做了一个小的指令来侦听文件输入的变化。
查看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 jqLite版本。
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="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-if
或ng-switch
)目标代理(输入)尚未呈现,