Se vuoi qualcosa di un po 'più elegante / integrato, puoi usare un decoratore per estendere la input
direttiva con il supporto di type=file
. L'avvertenza principale da tenere a mente è che questo metodo non funzionerà in IE9 poiché IE9 non ha implementato l'API File . L'uso di JavaScript per caricare dati binari indipendentemente dal tipo tramite XHR non è semplicemente possibile in modo nativo in IE9 o precedenti (l'uso di ActiveXObject
per accedere al filesystem locale non conta poiché l'utilizzo di ActiveX richiede solo problemi di sicurezza).
Questo metodo esatto richiede anche AngularJS 1.4.xo versioni successive, ma potresti essere in grado di adattarlo per usarlo $provide.decorator
piuttosto che angular.Module.decorator
- ho scritto questo riassunto per dimostrare come farlo mentre è conforme alla guida di stile AngularJS di John Papa :
(function() {
'use strict';
/**
* @ngdoc input
* @name input[file]
*
* @description
* Adds very basic support for ngModel to `input[type=file]` fields.
*
* Requires AngularJS 1.4.x or later. Does not support Internet Explorer 9 - the browser's
* implementation of `HTMLInputElement` must have a `files` property for file inputs.
*
* @param {string} ngModel
* Assignable AngularJS expression to data-bind to. The data-bound object will be an instance
* of {@link https://developer.mozilla.org/en-US/docs/Web/API/FileList `FileList`}.
* @param {string=} name Property name of the form under which the control is published.
* @param {string=} ngChange
* AngularJS expression to be executed when input changes due to user interaction with the
* input element.
*/
angular
.module('yourModuleNameHere')
.decorator('inputDirective', myInputFileDecorator);
myInputFileDecorator.$inject = ['$delegate', '$browser', '$sniffer', '$filter', '$parse'];
function myInputFileDecorator($delegate, $browser, $sniffer, $filter, $parse) {
var inputDirective = $delegate[0],
preLink = inputDirective.link.pre;
inputDirective.link.pre = function (scope, element, attr, ctrl) {
if (ctrl[0]) {
if (angular.lowercase(attr.type) === 'file') {
fileInputType(
scope, element, attr, ctrl[0], $sniffer, $browser, $filter, $parse);
} else {
preLink.apply(this, arguments);
}
}
};
return $delegate;
}
function fileInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {
element.on('change', function (ev) {
if (angular.isDefined(element[0].files)) {
ctrl.$setViewValue(element[0].files, ev && ev.type);
}
})
ctrl.$isEmpty = function (value) {
return !value || value.length === 0;
};
}
})();
Perché non è stato fatto in primo luogo? Il supporto di AngularJS è destinato a raggiungere solo IE9. Se non sei d'accordo con questa decisione e pensi che avrebbero dovuto inserirla comunque, salta il carro su Angular 2+ perché un migliore supporto moderno è letteralmente il motivo per cui Angular 2 esiste.
Il problema è (come accennato in precedenza) che senza il supporto del file API fare questo in modo corretto è impossibile per il core dato che la nostra linea di base è IE9 e polifilare questa roba è fuori discussione per core.
Inoltre, provare a gestire questo input in un modo che non è compatibile con più browser rende solo più difficile per le soluzioni di terze parti, che ora devono combattere / disabilitare / aggirare la soluzione principale.
...
Lo chiuderò proprio mentre chiudiamo il n. 1236. Angular 2 è stato creato per supportare i browser moderni e con quel supporto file sarà facilmente disponibile.