Jika Anda menginginkan sesuatu yang sedikit lebih elegan / terintegrasi, Anda dapat menggunakan dekorator untuk memperluas input
arahan dengan dukungan type=file
. Peringatan utama yang perlu diingat adalah bahwa metode ini tidak akan berfungsi di IE9 karena IE9 tidak mengimplementasikan File API . Menggunakan JavaScript untuk mengunggah data biner apa pun jenisnya melalui XHR sama sekali tidak mungkin secara bawaan di IE9 atau sebelumnya (penggunaan ActiveXObject
untuk mengakses sistem file lokal tidak masuk hitungan karena menggunakan ActiveX hanya meminta masalah keamanan).
Metode yang tepat ini juga memerlukan AngularJS 1.4.x atau yang lebih baru, tetapi Anda mungkin dapat mengadaptasi ini untuk digunakan $provide.decorator
daripada angular.Module.decorator
- Saya menulis inti ini untuk menunjukkan cara melakukannya sambil menyesuaikan dengan panduan gaya AngularJS 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;
};
}
})();
Mengapa ini tidak dilakukan sejak awal? Dukungan AngularJS dimaksudkan untuk menjangkau hanya sejauh IE9. Jika Anda tidak setuju dengan keputusan ini dan berpikir mereka seharusnya memasukkannya, maka lompati kereta ke Angular 2+ karena dukungan modern yang lebih baik adalah alasan mengapa Angular 2 ada.
Masalahnya adalah (seperti yang disebutkan sebelumnya) bahwa tanpa dukungan file api melakukan ini dengan benar tidak layak untuk inti mengingat baseline kami adalah IE9 dan polyfilling hal ini adalah keluar dari pertanyaan untuk core.
Selain itu mencoba menangani input ini dengan cara yang tidak kompatibel lintas-browser hanya mempersulit solusi pihak ketiga, yang sekarang harus berjuang / menonaktifkan / menyelesaikan solusi inti.
...
Saya akan menutup ini sama seperti kita menutup # 1236. Angular 2 sedang dibangun untuk mendukung browser modern dan dengan itu dukungan file akan mudah tersedia.