AngularJs: come verificare le modifiche nei campi di input del file?

Sono nuovo di angular. Sto cercando di leggere il percorso del file caricato dal campo “file” HTML ogni volta che un “cambiamento” avviene su questo campo. Se uso ‘onChange’ funziona, ma quando lo uso angular usando ‘ng-change’ non funziona.

 var DemoModule = angular.module("Demo",[]); DemoModule .controller("form-cntlr",function($scope){ $scope.selectFile = function() { $("#file").click(); } $scope.fileNameChaged = function() { alert("select file"); } });  

fileNameChaged () non sta mai chiamando. Firebug inoltre non mostra alcun errore.

Nessun supporto vincolante per il controllo Caricamento file

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

 

invece di

   

Puoi provare

  

Nota: ciò richiede che l’applicazione angular sia sempre in modalità di debug . Questo non funzionerà nel codice di produzione se la modalità di debug è disabilitata.

e nella tua funzione cambia invece di

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

Puoi provare

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

Di seguito è riportato un esempio di utilizzo del caricamento di file con trascinamento del caricamento del file di trascinamento potrebbe essere utile http://jsfiddle.net/danielzen/utp7j/

Informazioni sul caricamento di file angolari

URL per caricamento file AngularJS in ASP.Net

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

Caricamento multi-file nativo di AngularJs con avanzamento con NodeJS

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

ngUpload – Un servizio AngularJS per il caricamento di file usando iframe

http://ngmodules.org/modules/ngUpload

Ho fatto una piccola direttiva per ascoltare le modifiche ai file input.

Visualizza JSFiddle

view.html:

  

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.on('change', onChangeHandler); element.on('$destroy', function() { element.off(); }); } }; }); 

Questa è una raffinatezza di alcuni degli altri intorno, i dati finiranno in un modello di ng, che è normalmente quello che vuoi.

Markup (basta creare un file di dati di attributo in modo che la direttiva possa trovarlo)

  

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(); }); } }; }); 

Il modo pulito è scrivere la propria direttiva per associare l’evento “change”. Solo per farti sapere che IE9 non supporta FormData quindi non puoi davvero ottenere l’object file dall’evento change.

Puoi utilizzare la libreria di upload di file ng che supporta già IE con FileAPI polyfill e semplificare la pubblicazione del file sul server. Usa una direttiva per raggiungere questo objective.

   

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); }); } } }]; 

Ho ampliato l’idea di @Stuart Axon di aggiungere un’associazione a due vie per l’input del file (cioè consentire di reimpostare l’input reimpostando il valore del modello su 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(""); } }); } }; }]); 

dimostrazione

Simile ad alcune delle altre buone risposte qui, ho scritto una direttiva per risolvere questo problema, ma questa implementazione rispecchia più da vicino il modo angular di colbind gli eventi.

Puoi usare la direttiva in questo modo:

HTML

  

Come puoi vedere, puoi iniettare i file selezionati nel tuo gestore di eventi, dato che dovresti iniettare un object $ event in qualsiasi gestore di eventi 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); } }; }]); 

Questa direttiva passa anche i file selezionati:

 /** *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); } }); }); } }; }); 

L’HTML, come usarlo:

  

Nel mio controller:

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

Consiglio di creare una direttiva

  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}); }); }); } }; }]); 

questa direttiva può essere utilizzata molte volte, utilizza il proprio ambito e non dipende dall’ambito principale. Puoi anche dare alcuni parametri alla funzione del gestore. La funzione del gestore verrà chiamata con l’object scope, che era attivo quando hai cambiato l’input. $ applica aggiornamenti del tuo modello ogni volta che viene chiamato l’evento di cambiamento

La più semplice versione angular di jqLite.

JS:

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

HTML:

  

Base di soluzione troppo completa su:

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

Un modo semplice per hide il campo di input e sostituirlo con un’immagine, qui dopo una soluzione, che richiede anche un hack su angular ma che fa il lavoro [TriggerEvent non funziona come previsto]

La soluzione:

  • posiziona il campo di input nel display: none [il campo di input esiste nel DOM ma non è visibile]
  • posiziona l’immagine subito dopo Sull’immagine usa nb-clic () per triggersre un metodo

Quando l’immagine viene cliccata simula un’azione DOM “fai clic” sul campo di immissione. Et voilà!

  var tmpl = ''+ ' ' + ''; // 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!!! }; 

L’ho fatto in questo modo;

    
 // 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"); } 

Un altro modo interessante per ascoltare le modifiche apportate ai file è con un controllo sull’attributo ng-model del file di input. Fuori rotta FileModel è una direttiva personalizzata.

Come questo:

HTML ->

Codice JS ->

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

Spero che possa aiutare qualcuno.

Working Demo della direttiva “files-input” che funziona con ng-change 1

Per fare in modo che un elemento funzioni nella direttiva ng-change , ha bisogno di una direttiva personalizzata che funzioni con la direttiva ng-model .

  

La DEMO

 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"); }; }) 
   

AngularJS Input `type=file` Demo

Files

{{file.name}}

Gli elementi angolari (come l’elemento radice di una direttiva) sono oggetti jQuery [Lite]. Questo significa che possiamo registrare l’ascoltatore di eventi in questo modo:

 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) } 

Questa è la delega degli eventi jQuery. Qui, il listener è collegato all’elemento root della direttiva. Quando l’evento viene triggersto, diventerà visibile all’elemento registrato e jQuery determinerà se l’evento è originato da un elemento interno che corrisponde al selettore definito. Se lo fa, il gestore sparerà.

I vantaggi di questo metodo sono:

  • il gestore è associato all’elemento $ che verrà automaticamente ripulito quando l’ambito della direttiva viene distrutto.
  • nessun codice nel modello
  • funzionerà anche se il delegato di destinazione (input) non è ancora stato reso quando si registra il gestore di eventi (come quando si usa ng-if o ng-switch )

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