ng-model per “ (con direttiva DEMO)

Ho provato a usare ng-model sul tag di input con il file di tipo:

 

Ma dopo aver selezionato un file, nel controller, $ scope.vm.uploadme è ancora indefinito.

Come posso ottenere il file selezionato nel mio controller?

Ho creato una soluzione alternativa con la direttiva:

 .directive("fileread", [function () { return { scope: { fileread: "=" }, link: function (scope, element, attributes) { element.bind("change", function (changeEvent) { var reader = new FileReader(); reader.onload = function (loadEvent) { scope.$apply(function () { scope.fileread = loadEvent.target.result; }); } reader.readAsDataURL(changeEvent.target.files[0]); }); } } }]); 

E il tag di input diventa:

  

O se è necessaria solo la definizione del file:

 .directive("fileread", [function () { return { scope: { fileread: "=" }, link: function (scope, element, attributes) { element.bind("change", function (changeEvent) { scope.$apply(function () { scope.fileread = changeEvent.target.files[0]; // or all selected files: // scope.fileread = changeEvent.target.files; }); }); } } }]); 

Io uso questa direttiva:

 angular.module('appFilereader', []).directive('appFilereader', function($q) { var slice = Array.prototype.slice; return { restrict: 'A', require: '?ngModel', link: function(scope, element, attrs, ngModel) { if (!ngModel) return; ngModel.$render = function() {}; element.bind('change', function(e) { var element = e.target; $q.all(slice.call(element.files, 0).map(readFile)) .then(function(values) { if (element.multiple) ngModel.$setViewValue(values); else ngModel.$setViewValue(values.length ? values[0] : null); }); function readFile(file) { var deferred = $q.defer(); var reader = new FileReader(); reader.onload = function(e) { deferred.resolve(e.target.result); }; reader.onerror = function(e) { deferred.reject(e); }; reader.readAsDataURL(file); return deferred.promise; } }); //change } //link }; //return }); 

e invocarlo in questo modo:

  

La proprietà (editItem.editItem._attachments_uri.image) verrà popolata con i contenuti del file selezionato come data-uri (!).

Si prega di notare che questo script non caricherà nulla. Inserirà il tuo modello solo con il contenuto del tuo file codificato ad un data-uri (base64).

Guarda qui una demo funzionante: http://plnkr.co/CMiHKv2BEidM9SShm9Vv

Questo è un addendum alla soluzione di @ endy-tjahjono.

Ho finito per non essere in grado di ottenere il valore di uploadme dall’ambito. Anche se uploadme in HTML è stato visibilmente aggiornato dalla direttiva, non potrei ancora accedere al suo valore da $ scope.uploadme. Sono stato in grado di impostare il suo valore dall’ambito, però. Misterioso, giusto ..?

Come si è scoperto, un ambito figlio è stato creato dalla direttiva e l’ambito figlio ha avuto il suo uploadme .

La soluzione era usare un object piuttosto che un primitivo per mantenere il valore di uploadme .

Nel controller ho:

 $scope.uploadme = {}; $scope.uploadme.src = ""; 

e nel codice HTML:

    

Non ci sono modifiche alla direttiva.

Ora, tutto funziona come previsto. Posso prendere il valore di uploadme.src dal mio controller usando $ scope.uploadme.

Demo di lavoro della direttiva che funziona con ng-model

Come abilitare per lavorare con ng-model

La direttiva core ng-model non funziona con out of the box.

Questa direttiva personalizzata abilita il ng-model e ha l'ulteriore vantaggio di abilitare le direttive ng-change , ng-required e ng-form a lavorare con .

 angular.module("app",[]); angular.module("app").directive("selectNgFiles", function() { return { require: "ngModel", link: function postLink(scope,elem,attrs,ngModel) { elem.on("change", function(e) { var files = elem[0].files; ngModel.$setViewValue(files); }) } } }); 
   

AngularJS Input `type=file` Demo

NameDateSizeType
{{file.name}} {{file.lastModified | date : 'MMMdd,yyyy'}} {{file.size}} {{file.type}}

Ciao ragazzi, ho creato una direttiva e mi sono iscritto a Bower.

questa libreria ti aiuterà a modellare il file di input, non solo a restituire i dati dei file ma anche a file dataurl o base 64.

 { "lastModified": 1438583972000, "lastModifiedDate": "2015-08-03T06:39:32.000Z", "name": "gitignore_global.txt", "size": 236, "type": "text/plain", "data": "data:text/plain;base64,DQojaWdub3JlIHRodW1ibmFpbHMgY3JlYXRlZCBieSB3aW5kb3dz…xoDQoqLmJhaw0KKi5jYWNoZQ0KKi5pbGsNCioubG9nDQoqLmRsbA0KKi5saWINCiouc2JyDQo=" } 

https://github.com/mistralworks/ng-file-model/

La speranza ti aiuterà

Questa è una versione leggermente modificata che consente di specificare il nome dell’attributo nell’ambito, proprio come si farebbe con ng-model, l’uso:

   

Direttiva:

 .directive('myUpload', function() { return { link: function postLink(scope, element, attrs) { element.find("input").bind("change", function(changeEvent) { var reader = new FileReader(); reader.onload = function(loadEvent) { scope.$apply(function() { scope[attrs.key] = loadEvent.target.result; }); } if (typeof(changeEvent.target.files[0]) === 'object') { reader.readAsDataURL(changeEvent.target.files[0]); }; }); }, controller: 'FileUploadCtrl', template: '' + '' + 'Replace Image' + '' + '', restrict: 'E' }; }); 

Per l’immissione di più file usando lodash o underscore:

 .directive("fileread", [function () { return { scope: { fileread: "=" }, link: function (scope, element, attributes) { element.bind("change", function (changeEvent) { return _.map(changeEvent.target.files, function(file){ scope.fileread = []; var reader = new FileReader(); reader.onload = function (loadEvent) { scope.$apply(function () { scope.fileread.push(loadEvent.target.result); }); } reader.readAsDataURL(file); }); }); } } }]); 

Ho dovuto fare lo stesso su più input, quindi ho aggiornato il metodo @Endy Tjahjono. Restituisce un array contenente tutti i file letti.

  .directive("fileread", function () { return { scope: { fileread: "=" }, link: function (scope, element, attributes) { element.bind("change", function (changeEvent) { var readers = [] , files = changeEvent.target.files , datas = [] ; for ( var i = 0 ; i < files.length ; i++ ) { readers[ i ] = new FileReader(); readers[ i ].onload = function (loadEvent) { datas.push( loadEvent.target.result ); if ( datas.length === files.length ){ scope.$apply(function () { scope.fileread = datas; }); } } readers[ i ].readAsDataURL( files[i] ); } }); } } }); 
 function filesModelDirective(){ return { controller: function($parse, $element, $attrs, $scope){ var exp = $parse($attrs.filesModel); $element.on('change', function(){ exp.assign($scope, this.files[0]); $scope.$apply(); }); } }; } app.directive('filesModel', filesModelDirective); 

Ho dovuto modificare la direttiva di Endy in modo da poter ottenere Last Modified, lastModifiedDate, nome, dimensione, tipo e dati oltre a poter ottenere una matrice di file. Per quelli di voi che avevano bisogno di queste funzionalità extra, ecco qui.

AGGIORNAMENTO: Ho trovato un bug in cui, se si seleziona il / i file / i e poi si va di nuovo a selezionare ma si annulla, i file non vengono mai deselezionati come appare. Così ho aggiornato il mio codice per risolverlo.

  .directive("fileread", function () { return { scope: { fileread: "=" }, link: function (scope, element, attributes) { element.bind("change", function (changeEvent) { var readers = [] , files = changeEvent.target.files , datas = [] ; if(!files.length){ scope.$apply(function () { scope.fileread = []; }); return; } for ( var i = 0 ; i < files.length ; i++ ) { readers[ i ] = new FileReader(); readers[ i ].index = i; readers[ i ].onload = function (loadEvent) { var index = loadEvent.target.index; datas.push({ lastModified: files[index].lastModified, lastModifiedDate: files[index].lastModifiedDate, name: files[index].name, size: files[index].size, type: files[index].type, data: loadEvent.target.result }); if ( datas.length === files.length ){ scope.$apply(function () { scope.fileread = datas; }); } }; readers[ i ].readAsDataURL( files[i] ); } }); } } }); 

Prova questo, questo funziona per me in JS angular

  let fileToUpload = `${documentLocation}/${documentType}.pdf`; let absoluteFilePath = path.resolve(__dirname, fileToUpload); console.log(`Uploading document ${absoluteFilePath}`); element.all(by.css("input[type='file']")).sendKeys(absoluteFilePath);