ng-model para “ (con la directiva DEMO)

Traté de usar ng-model en la etiqueta de entrada con el tipo de archivo:

 

Pero después de seleccionar un archivo, en el controlador, $ scope.vm.uploadme todavía no está definido.

¿Cómo obtengo el archivo seleccionado en mi controlador?

Creé una solución con directiva:

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

Y la etiqueta de entrada se convierte en:

  

O si solo se necesita la definición del archivo:

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

Yo uso esta directiva:

 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 así:

  

La propiedad (editItem.editItem._attachments_uri.image) se completará con los contenidos del archivo que seleccione como un uri de datos (!).

Tenga en cuenta que este script no cargará nada. Solo completará su modelo con los contenidos de su archivo codificado como ad-data (base64).

Vea una demostración funcional aquí: http://plnkr.co/CMiHKv2BEidM9SShm9Vv

Este es un apéndice a la solución de @ endy-tjahjono.

Terminé sin poder obtener el valor de uploadme del scope. Aunque uploadme en el HTML fue visiblemente actualizado por la directiva, aún no pude acceder a su valor por $ scope.uploadme. Sin embargo, pude establecer su valor desde el scope. Misterioso, ¿verdad …?

Resultó que la directiva creó un scope para niños y el ámbito para niños tenía su propia carga .

La solución fue usar un objeto en lugar de una primitiva para mantener el valor de uploadme .

En el controlador tengo:

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

y en el HTML:

    

No hay cambios en la directiva.

Ahora, todo funciona como se espera. Puedo tomar el valor de uploadme.src desde mi controlador utilizando $ scope.uploadme.

Demostración de trabajo de la directiva que funciona con ng-model

Cómo habilitar para trabajar con ng-model

La directiva core ng-model no funciona con fuera de la caja.

Esta directiva personalizada habilita ng-model y tiene el beneficio adicional de permitir que las directivas ng-change , ng-required y ng-form funcionen 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}}

Hola chicos, creo una directiva y me registro en Bower.

Esta lib lo ayudará a modelar el archivo de entrada, no solo devolverá los datos del archivo sino también el archivo 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/

Hope te ayudará

Esta es una versión ligeramente modificada que le permite especificar el nombre del atributo en el scope, tal como lo haría con el uso de ng-model:

   

Directiva:

 .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' }; }); 

Para múltiples archivos de entrada usando lodash o guión bajo:

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

Tuve que hacer lo mismo en múltiples entradas, así que actualicé el método @Endy Tjahjono. Devuelve una matriz que contiene todos los archivos leídos.

  .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); 

Tuve que modificar la directiva de Endy para poder obtener Last Modified, lastModifiedDate, nombre, tamaño, tipo y datos, así como poder obtener una matriz de archivos. Para aquellos de ustedes que necesitan estas características adicionales, aquí tienen.

ACTUALIZACIÓN: Encontré un error donde si seleccionas el archivo (s) y luego vas a seleccionar nuevamente pero cancelas, los archivos nunca se deseleccionan como aparece. Así que actualicé mi código para arreglar eso.

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

Prueba esto, esto está funcionando para mí en 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);