AngularJs: Как проверить наличие изменений в полях ввода файлов?
Я новичок в угловой. Я пытаюсь прочитать загруженный путь к файлу из поля HTML ' file 'всякий раз, когда в этом поле происходит "изменение". Если я использую 'onChange, после чего он работает, но когда я использую его угловым способом с использованием НГ-изменить это не получится.
<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 также не показывает никаких ошибок.
14 ответов:
нет поддержки привязки для управления загрузкой файлов
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/
Угловой Файл Загрузить Информацию
URL для загрузки файла AngularJS ASP.Net
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
Я сделал небольшую директиву для прослушивания изменений ввода файлов.
вид.html:
<input type="file" custom-on-change="uploadFile">контроллер.js:
app.controller('myCtrl', function($scope){ $scope.uploadFile = function(event){ var files = event.target.files; }; });
это уточнение некоторых других вокруг, данные будут в конечном итоге в НГ-модель, которая обычно то, что вы хотите.
разметка (просто сделайте файл данных атрибута, чтобы директива могла его найти)
<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(); }); } }; });
чистый способ-написать свою собственную директиву для привязки к событию "change". Просто чтобы вы знали, что IE9 не поддерживает FormData, поэтому вы не можете получить объект file из события change.
можно использовать ng-file-upload библиотека, которая уже поддерживает IE с 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, чтобы добавить двустороннюю привязку для ввода файла (т. е. разрешить сброс ввода путем сброса значения модели обратно в null):
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)" />Как вы можете видеть, вы можете ввести выбранные файлы в обработчик событий, как вы бы ввели объект $event в любое событие ng обработчик.
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}); }); }); } }; }]);эта директива может использоваться много раз, она использует свою собственную область и не зависит от родительской области. Вы также можете дать некоторые параметры функции обработчика. Функция обработчика будет вызвана с объектом scope, который был активен при изменении входных данных. $применить обновляет модель каждый раз, когда событие изменения называется
самая простая угловая версия 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 не работает так, как ожидалось]
решение:
- поместите поле ввода в display:none [поле ввода существует в DOM, но не видно]
- поместите изображение сразу после На использование изображения НБ-нажмите кнопку (), чтобы активировать метод
при нажатии на изображение имитировать действие DOM "нажмите" на поле ввода. И вуаля!
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 входного файла. Off course FileModel-это пользовательская директива.
такой:
HTML ->
<input type="file" file-model="change.fnEvidence">код JS ->
$scope.$watch('change.fnEvidence', function() { alert("has changed"); });надеюсь, что это может помочь кому-то.
рабочая демонстрация директивы" files-input", которая работает с
ng-change1сделать
<input type=file>элемент work the 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-ifилиng-switch)
Comments