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