Angular doesn't support binding to file-type inputs,但我使用许多其他答案拼凑出一个解决方案。
app.directive('filePicker', filePicker);
filePicker.$inject = ['$log', '$document'];
function filePicker($log,$document) {
var directive = {
restrict: 'A',
require: 'ngModel',
scope: {
ngModel: '='
},
link: _link
};
return directive;
function _link(scope, elem, attrs, ngModel) {
// check if valid input element
if( elem[0].nodeName.toLowerCase() !== 'input' ) {
$log.warn('filePicker:', 'The directive will work only for input element, actual element is a', elem[0].nodeName.toLowerCase());
return;
}
// check if valid input type file
if( attrs.type != 'file' ) {
$log.warn('filePicker:', 'Expected input type file, received instead:', attrs.type, 'on element:', elem);
return;
}
// listen for input change
elem.on('change', function(e) {
// get files
var files = elem[0].files;
// update model value
scope.$apply(function() {
attrs.multiple ? scope.ngModel = files : scope.ngModel = files[0];
});
});
scope.$watch('ngModel', function() {
if (!scope.ngModel)
elem[0].value = ""; // clears all files; there's no way to remove only some
});
}
}
This solution 向我展示了如何使用指令来实现与 ng-model 的自定义绑定。它可以访问文件的内容,因此如果您需要该功能,可以将其添加回我的解决方案中。
但是,它的绑定存在一些问题。它会正确设置我的variable_in_scope 的值,但如果有其他东西绑定到variable_in_scope 的值,它们就不会更新。 The trick was to use isolate scope and $apply. 那你就不用搞这个$setViewValue 业务了。只需设置它并忘记它。
这让我达到了单向绑定。但是,如果我将值设置为variable_in_scope,文件选择器仍然显示我选择了原始文件。就我而言,我真正想做的就是清除所选文件。我发现了the Javascript magic to do this,并在ngModel上设置了一个$watch来触发它。
如果您想以编程方式将文件设置为不同的值,祝您好运,因为FileList is read-only。 magic trick 可让您清除 FileList,但您无法添加任何内容。也许您可以创建一个新的FileList 并将其分配给.files,但粗略一瞥我并没有看到这样做的方法。