AngularJs: Como verificar se há mudanças nos campos de input do arquivo?

Eu sou novo em angular. Eu estou tentando ler o caminho do arquivo enviado do campo ‘arquivo’ HTML sempre que uma ‘alteração’ acontece neste campo. Se eu uso ‘onChange’ funciona mas quando eu uso angularmente usando ‘ng-change’ não funciona.

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

fileNameChaged () nunca está chamando. O Firebug também não mostra nenhum erro.

   

Não há suporte a binding para o controle de upload de arquivo

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

 

ao invés de

   

você pode tentar

  

Nota: isso requer que o aplicativo angular esteja sempre no modo de debugging . Isso não funcionará no código de produção se o modo de debugging estiver desativado.

e na sua function muda em vez de

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

você pode tentar

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

Abaixo está um exemplo de trabalho de upload de arquivos com o upload do arquivo de arrastar e soltar pode ser útil http://jsfiddle.net/danielzen/utp7j/

Informações de upload de arquivo angular

URL para upload de arquivo AngularJS no ASP.Net

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

Upload nativo de vários arquivos do AngularJs com progresso com o NodeJS

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

ngUpload – Um serviço AngularJS para upload de arquivos usando iframe

http://ngmodules.org/modules/ngUpload

Fiz uma pequena diretiva para ouvir as alterações na input de arquivos.

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

Este é um refinamento de alguns dos outros ao redor, os dados vão acabar em um modelo ng, que normalmente é o que você quer.

Marcação (basta criar um arquivo de dados de atributo para que a diretiva possa encontrá-lo)

  

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

A maneira limpa é escrever sua própria diretiva para ligar ao evento “change”. Apenas para que você saiba que o IE9 não suporta FormData, então você não pode realmente obter o object de arquivo do evento de mudança.

Você pode usar a biblioteca ng-file-upload que já suporta o IE com o polyfill FileAPI e simplifica a postagem do arquivo no servidor. Ele usa uma diretiva para conseguir isso.

   

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

Eu expandi a idéia de @Stuart Axon para adicionar uma binding bidirecional para a input de arquivo (isto é, permitir redefinir a input redefinindo o valor do modelo de volta para 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(""); } }); } }; }]); 

Demonstração

Semelhante a algumas das outras boas respostas aqui, eu escrevi uma diretiva para resolver esse problema, mas essa implementação espelha mais de perto o modo angular de append events.

Você pode usar a diretiva assim:

HTML

  

Como você pode ver, é possível injetar os arquivos selecionados no manipulador de events, pois você deve injetar um object $ event em qualquer manipulador de events 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); } }; }]); 

Esta diretiva também passa os arquivos selecionados:

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

O HTML, como usá-lo:

  

No meu controlador:

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

Eu recomendo criar uma diretiva

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

Essa diretiva pode ser usada muitas vezes, ela usa seu próprio escopo e não depende do escopo pai. Você também pode dar alguns parâmetros para a function de manipulador. A function de manipulador será chamada com o object de escopo, que estava ativo quando você alterou a input. $ apply atualiza seu modelo toda vez que o evento de mudança é chamado

A versão jqLite Angular mais simples.

JS:

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

HTML:

  

Solução muito completa baseada em:

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

Uma maneira simples de ocultar o campo de input e substituí-lo por uma imagem, aqui após uma solução, que também requer um corte no angular, mas que faz o trabalho [TriggerEvent não funciona como esperado]

A solução:

  • coloque o campo de input em display: none [o campo de input existe no DOM, mas não é visível]
  • coloque sua imagem logo após Na imagem use nb-click () para ativar um método

Quando a imagem é clicada, simule uma ação DOM ‘clique’ no campo de input. E 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!!! }; 

Eu fiz assim;

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

Outra maneira interessante de ouvir as mudanças na input do arquivo é com uma observação do atributo ng-model do arquivo de input. Fora do curso FileModel é uma diretiva personalizada.

Como isso:

HTML ->

Código JS ->

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

Espero que isso possa ajudar alguém.

Demonstração de trabalho de “arquivos de input” directiva que funciona com ng-change 1

Para fazer um elemento funcionar na diretiva ng-change , ele precisa de uma diretiva customizada que funcione com a diretiva ng-model .

  

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

Elementos angulares (como o elemento raiz de uma diretiva) são objects jQuery [Lite]. Isso significa que podemos registrar o ouvinte de evento da seguinte forma:

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

Esta é a delegação de events do jQuery. Aqui, o ouvinte é anexado ao elemento raiz da diretiva. Quando o evento é acionado, ele irá aparecer no elemento registrado e o jQuery determinará se o evento foi originado em um elemento interno que corresponde ao seletor definido. Em caso afirmativo, o manipulador será acionado.

Benefícios deste método são:

  • o manipulador é ligado ao elemento $, que será automaticamente limpo quando o escopo da diretiva for destruído.
  • nenhum código no modelo
  • funcionará mesmo se o delegado de destino (input) ainda não tiver sido processado quando você registrar o manipulador de events (por exemplo, ao usar ng-if ou ng-switch )

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