Nếu bạn muốn một cái gì đó thanh lịch / tích hợp hơn một chút, bạn có thể sử dụng một công cụ trang trí để mở rộng input
chỉ thị với sự hỗ trợ cho type=file
. Lưu ý chính cần lưu ý là phương pháp này sẽ không hoạt động trong IE9 do IE9 không triển khai API tệp . Sử dụng JavaScript để tải lên dữ liệu nhị phân bất kể loại thông qua XHR đơn giản là không thể có trong IE9 hoặc trước đó (sử dụng ActiveXObject
để truy cập hệ thống tệp cục bộ không được tính là sử dụng ActiveX chỉ yêu cầu các vấn đề bảo mật).
Phương pháp chính xác này cũng yêu cầu AngularJS 1.4.x trở lên, nhưng bạn có thể điều chỉnh cách này để sử dụng $provide.decorator
chứ không phải angular.Module.decorator
- Tôi đã viết ý chính này để trình bày cách thực hiện trong khi tuân thủ hướng dẫn kiểu AngularJS của 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;
};
}
})();
Tại sao điều này không được thực hiện ở nơi đầu tiên? Hỗ trợ AngularJS chỉ nhằm mục đích trở lại xa như IE9. Nếu bạn không đồng ý với quyết định này và nghĩ rằng dù sao họ cũng nên đưa nó vào, thì hãy nhảy chiếc xe sang Angular 2+ vì sự hỗ trợ hiện đại tốt hơn chính là lý do tại sao Angular 2 tồn tại.
Vấn đề là (như đã được đề cập trước đó) rằng không có hỗ trợ api tập tin làm điều này đúng cách là không khả thi đối với lõi do đường cơ sở của chúng tôi là IE9 và việc điền vào công cụ này không nằm trong câu hỏi đối với lõi.
Ngoài ra, việc cố gắng xử lý đầu vào này theo cách không tương thích với nhiều trình duyệt chỉ khiến cho các giải pháp của bên thứ 3 trở nên khó khăn hơn, hiện phải chống lại / vô hiệu hóa / giải quyết giải pháp cốt lõi.
...
Tôi sẽ đóng cái này khi chúng tôi đóng # 1236. Angular 2 đang được xây dựng để hỗ trợ các trình duyệt hiện đại và với sự hỗ trợ tập tin đó sẽ dễ dàng có sẵn.