ngmodeloptions angularjs angularjs-ng-model angularjs-fileupload

angularjs - ngmodeloptions - ng-href angular 4



ng-model para `<tipo de entrada=" archivo "/>`(con la directiva DEMO) (11)

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

<input type="file" ng-model="vm.uploadme" />

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

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


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

Cómo habilitar <input type="file"> para trabajar con ng-model

La directiva core ng-model no funciona con <input type="file" fuera de la caja.

Esta directiva personalizada habilita ng-model y tiene la ventaja adicional de habilitar las directivas ng-change , ng-required y ng-form para trabajar con <input type="file"> .

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

<script src="//unpkg.com/angular/angular.js"></script> <body ng-app="app"> <h1>AngularJS Input `type=file` Demo</h1> <input type="file" select-ng-files ng-model="fileArray" multiple> <code><table ng-show="fileArray.length"> <tr><td>Name</td><td>Date</td><td>Size</td><td>Type</td><tr> <tr ng-repeat="file in fileArray"> <td>{{file.name}}</td> <td>{{file.lastModified | date : ''MMMdd,yyyy''}}</td> <td>{{file.size}}</td> <td>{{file.type}}</td> </tr> </table></code> </body>


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

<myUpload key="file"></myUpload>

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: ''<span class="btn btn-success fileinput-button">'' + ''<i class="glyphicon glyphicon-plus"></i>'' + ''<span>Replace Image</span>'' + ''<input type="file" accept="image/*" name="files[]" multiple="">'' + ''</span>'', restrict: ''E'' }; });


Este es un addendum a la solución de @ endy-tjahjono.

Terminé no pudiendo obtener el valor de uploadme desde el alcance. A pesar de que uploadme en el HTML estaba visiblemente actualizado por la directiva, todavía no podía acceder a su valor por $ scope.uploadme. Sin embargo, pude establecer su valor desde el alcance. Misterioso, ¿verdad ..?

Al final resultó que, la directiva creó un ámbito secundario, y el ámbito secundario tenía su propio uploadme .

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:

<input type="file" fileread="uploadme.src"/> <input type="text" ng-model="uploadme.src"/>

No hay cambios en la directiva.

Ahora, todo funciona como se esperaba. Puedo tomar el valor de uploadme.src de mi controlador usando $ scope.uploadme.


He creado una solución con la 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:

<input type="file" fileread="vm.uploadme" />

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


Hola chicos creo una directiva y me registré en bower.

esta biblioteca le ayudará a modelar el archivo de entrada, no solo a devolver datos de archivos sino también a 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 esperanza te ayudara


Intenta esto, esto me funciona 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);


Para la entrada de múltiples archivos 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 entradas múltiples, 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] ); } }); } } });


Tuve que modificar la directiva de Endy para poder obtener la última modificación, la última fecha de modificación, el nombre, el tamaño, el tipo y los datos, así como poder obtener una variedad de archivos. Para aquellos de ustedes que necesitaban estas características adicionales, aquí van.

ACTUALIZACIÓN: Encontré un error en el que si selecciona los archivos y luego vuelve a seleccionarlos pero cancela, 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] ); } }); } } });


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

Y lo invocamos así:

<input type="file" ng-model="editItem._attachments_uri.image" accept="image/*" app-filereader />

La propiedad (editItem.editItem._attachments_uri.image) se rellenará con el contenido del archivo que seleccione como data-uri (!).

Tenga en cuenta que este script no cargará nada. Solo llenará su modelo con el contenido de su archivo codificado y un data-uri (base64).

Echa un vistazo a una demostración de trabajo aquí: http://plnkr.co/CMiHKv2BEidM9SShm9Vv


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