Wenn Sie etwas eleganteres / integrierteres wünschen, können Sie einen Dekorateur verwenden , um die input
Richtlinie mit Unterstützung für zu erweitern type=file
. Die wichtigste Einschränkung ist, dass diese Methode in IE9 nicht funktioniert, da IE9 die Datei-API nicht implementiert hat . Die Verwendung von JavaScript zum Hochladen von Binärdaten unabhängig vom Typ über XHR ist in IE9 oder früher einfach nicht nativ möglich (Verwendung vonActiveXObject
für den Zugriff auf das lokale Dateisystem zählt nicht, da die Verwendung von ActiveX nur nach Sicherheitsproblemen fragt).
Für diese genaue Methode ist auch AngularJS 1.4.x oder höher erforderlich. Möglicherweise können Sie dies jedoch anpassen, $provide.decorator
anstatt es zu verwenden. angular.Module.decorator
Ich habe diesen Kern geschrieben , um zu demonstrieren, wie dies unter Einhaltung des AngularJS- Styleguides von John Papa zu tun ist :
(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;
};
}
})();
Warum wurde das überhaupt nicht gemacht? Die AngularJS-Unterstützung soll nur bis zum IE9 zurückreichen. Wenn Sie mit dieser Entscheidung nicht einverstanden sind und der Meinung sind, dass sie dies sowieso hätten tun sollen, dann springen Sie mit dem Wagen zu Angular 2+, da Angular 2 buchstäblich eine bessere moderne Unterstützung bietet.
Das Problem ist (wie bereits erwähnt), dass dies ohne die Unterstützung der Datei-API für den Core nicht möglich ist, da unsere Basis IE9 ist und das Polyfilling dieses Materials für den Core nicht in Frage kommt.
Der Versuch, diese Eingabe auf eine Weise zu verarbeiten, die nicht browserübergreifend kompatibel ist, erschwert nur Lösungen von Drittanbietern, die nun die Kernlösung bekämpfen / deaktivieren / umgehen müssen.
...
Ich werde dies schließen, gerade als wir # 1236 geschlossen haben. Angular 2 wird entwickelt, um moderne Browser zu unterstützen, und mit dieser Datei wird die Unterstützung leicht verfügbar sein.