angularjs - insertar - ngvalue angular js
Archivo seleccionado con Angular JS (7)
Me gustaría recoger un archivo con AngularJS:
HTML:
<div ng-controller="TopMenuCtrl">
<button class="btn" ng-click="isCollapsed = !isCollapsed">Toggle collapse</button>
<input type="file" ng-model="filepick" ng-change="pickimg()" multiple />
<output id="list"></output>
</div>
javascript:
angular.module(''plunker'', [''ui.bootstrap'']);
function TopMenuCtrl($scope) {
$scope.pickimg = function() {
alert(''a'');
};
}
¿Cómo puedo vincular la acción de cambio de archivo de entrada en la función pickimg
AngularJS? ¿Y cómo puedo manipular los archivos cargados después?
A continuación es mi enfoque con una directiva.
Directiva
angular
.module(''yourModule'')
.directive(''fileChange'', function() {
return {
restrict: ''A'',
scope: {
handler: ''&''
},
link: function (scope, element) {
element.on(''change'', function (event) {
scope.$apply(function(){
scope.handler({files: event.target.files});
});
});
}
};
});
HTML
<input type="file" file-change handler="fileSelect(files)">
Controlador
fileSelect = function (files) {
var file = files[0];
//you will get the file object here
}
Angular aún no admite ng-change para la entrada [tipo = archivo], por lo que usted mismo debe implementar la implementación de cambio.
Primero, en el HTML, defina Javascript para onchange de la siguiente manera:
<input ng-model="photo"
onchange="angular.element(this).scope().file_changed(this)"
type="file" accept="image/*" />
Y luego en su código de controlador Angular, defina la función:
$scope.file_changed = function(element) {
$scope.$apply(function(scope) {
var photofile = element.files[0];
var reader = new FileReader();
reader.onload = function(e) {
// handle onload
};
reader.readAsDataURL(photofile);
});
};
Aquí hay una directiva ligera que escribí para resolver este problema, que refleja la forma angular de adjuntar eventos.
Puedes usar la directiva así:
HTML
<input type="file" file-change="yourHandler($event, files)" />
Como puede ver, puede inyectar los archivos seleccionados en su controlador de eventos, como inyectaría un objeto $ event en cualquier controlador de eventos 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);
}
};
}]);
He hecho una directiva. Aquí está el fiddle .
La aplicación funciona para seleccionar csvs y mostrarlos como tablas html.
Con la directiva de cambio de archivo, podría definir la lógica de lectura y análisis de archivos (con servicios, puede ser) en los controladores, lo que le proporcionará más flexibilidad. Solo para la nota, la función ac.onFileChange
pasada al atributo on-file-change se convertirá en el controlador para el evento de cambio de entrada dentro de la directiva.
(function (angular, document) {
angular
.module("app.directives", [])
.directive("onFileChange", ["$parse", function ($parse) {
return {
restrict: "A",
link: function (scope, ele, attrs) {
// onFileChange is a reference to the same function which you would define
// in the controller. So that you can keep your logic in the controller.
var onFileChange = $parse(attrs.onFileChange.split(//(/)[0])(scope)
ele.on("change", onFileChange)
ele.removeAttr("on-file-change")
}
}
}])
angular
.module("app.services", [])
.service("Parse", ["$q", function ($q) {
var Parse = this
Parse.csvAsGrid = function (file) {
return $q(function (resolve, reject) {
try {
Papa.parse(file, {
complete: function (results) {
resolve(results.data)
}
})
} catch (e) {
reject(e)
}
})
}
}])
angular
.module("app", ["app.directives", "app.services"])
.controller("appCtrl", ["$scope", "Parse", function ($scope, Parse) {
var ac = this
ac.fileName = ""
ac.onFileChange = function (event) {
if (!event.target.files.length) {
return
}
Parse.csvAsGrid(event.target.files[0]).then(outputAsTable)
}
ac.clearInput = function (event) {
var input = angular.element(event.target)
input.val("")
document.getElementById("output").innerHTML = ""
}
function outputAsTable(grid) {
var table = [''<table border="1">'']
grid.map(function (row) {
table.push(''<tr>'')
row.map(function (cell) {
table.push(''<td>'' + cell.replace(/["'']/g, "") + ''</td>'')
})
table.push(''</tr>'')
})
table.push(''</table>'')
document.getElementById("output").innerHTML = table.join("/n")
}
}])
})(angular, document)
table {
border-collapse: collapse;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/4.1.2/papaparse.min.js"></script>
<div ng-app="app" ng-controller="appCtrl as ac">
<label>Select a comma delimited CSV file:-</label>
<input id="filePicker" type="file" on-file-change="ac.onFileChange(event)" ng-click="ac.clearInput($event)"/>{{ac.fileName}}
</div>
<div id="output"></div>
La solución de Teemu no funcionará para IE9.
He reunido una directiva angular simple con Flash polyfill para navegadores que no admiten HTML5 FormData, también puede escuchar el evento de progreso de carga.
https://github.com/danialfarid/ng-file-upload Demo: http://angular-file-upload.appspot.com/
<script src="angular.min.js"></script>
<script src="ng-file-upload.js"></script>
<div ng-controller="MyCtrl">
<input type="text" ng-model="additionalData">
<div ngf-select ng-model="files" >
</div>
controlador:
Upload.upload({
url: ''my/upload/url'',
data: additionalData,
file: files
}).then(success, error, progress);
Usé el método anterior tratando de cargar una imagen de vista previa cuando se selecciona un nuevo archivo, sin embargo, no funcionó cuando lo probé de esa manera:
$scope.file_changed = function(element, $scope) {
$scope.$apply(function(scope) {
var photofile = element.files[0];
var reader = new FileReader();
reader.onload = function(e) {
$scope.prev_img = e.target.result;
};
reader.readAsDataURL(photofile);
});
});
Busqué más en él y descubrí que $ scope. $ Apply debería estar dentro del reader.onLoad, de lo contrario, cambiar las variables de $ scope no funcionaría, así que hice lo siguiente y funcionó:
$scope.file_changed = function(element) {
var photofile = element.files[0];
var reader = new FileReader();
reader.onload = function(e) {
$scope.$apply(function() {
$scope.prev_img = e.target.result;
});
};
reader.readAsDataURL(photofile);
};
Usando la respuesta de Madura de arriba, aquí está el flujo completo para leer un archivo JSON local:
Crear directiva:
angular
.module(''app.services'')
.directive(''fileChange'', function() {
return {
restrict: ''A'',
scope: {
handler: ''&''
},
link: function (scope, element) {
element.on(''change'', function (event) {
scope.$apply(function(){
scope.handler({files: event.target.files});
});
});
}
};
});
HTML:
<input type="file" file-change handler="fileSelect(files)">
Javascript:
$scope.fileSelect = function(files) {
var file = files[0];
var reader = new FileReader();
reader.onload = function(e) {
console.log("on load", e.target.result);
}
reader.readAsText(file);
}