如何双向绑定到type="文件"用ng模型输入
How do I two-way bind to a type="file" input with ng-model?
基本上我想这样做:
<input type="file" ng-model="variable_in_scope">
当我选择一个文件时,variable_in_scope
应该被分配给被选择的文件对象。此外,如果variable_in_scope
的值在我的页面的其他地方被改变,它应该更新"选择文件"按钮旁边的文本,以表明所选择的文件已经改变。
对于任何其他类型的输入,这都可以工作。
我不需要做任何花哨的事情,比如实际看到文件的内容。最后,我想发布它,但我发现您可以通过将文件对象设置为FormData对象来实现这一点,而无需实际将内容读取到Javascript-land中。
我还发现了其他关于angular选择文件的问题,但是没有一个有双向绑定的解决方案。
我对另一个问题的回答提供了一种使用ng-model
完成此操作的方法,但由于该问题不是专门关于双向绑定的(并且我的答案很难在那里找到),我将在这里复制它:
app.directive('bindFile', [function () {
return {
require: "ngModel",
restrict: 'A',
link: function ($scope, el, attrs, ngModel) {
el.bind('change', function (event) {
ngModel.$setViewValue(event.target.files[0]);
$scope.$apply();
});
$scope.$watch(function () {
return ngModel.$viewValue;
}, function (value) {
if (!value) {
el.val("");
}
});
}
};
}]);
要使用它,你只需要将它添加到你的angular模块中,并在你想要使用它的文件选择器中包含一个bind-file
属性。
Angular不支持绑定到文件类型的输入,但我使用了许多其他答案拼凑了一个解决方案。
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
});
}
}
这个解决方案向我展示了如何使用指令来实现对ng-model的自定义绑定。它允许访问文件的内容,所以如果你需要这个功能,你可以把它添加到我的解决方案中。
但是,它的绑定有一些问题。它将正确设置我的variable_in_scope
的值,但如果有其他东西绑定到variable_in_scope
的值,它们将不会更新。诀窍是使用隔离作用域和$apply
。那你就不用再插手$setViewValue
的事了。设置好了就忘了它吧。
这让我知道了单向绑定。但是,如果我将值设置为variable_in_scope
,那么文件选择器仍然显示我选中了原始文件。在我的例子中,我真正想做的就是清除选中的文件。我发现了Javascript魔法来做到这一点,并在ngModel
上设置了$watch
来触发它。
如果您想以编程方式将文件设置为不同的值,那么祝您好运,因为FileList
是只读的。这个魔术可以让你清除FileList
,但是你不能添加任何东西。也许你可以创建一个新的FileList
并将其分配给.files
,但粗略地看了一下,我没有看到这样做的方法。
help for me: FileUploader
用display: none隐藏输入元素;然后在输入元素的顶部使用一个标签,并将一个标签连接到作用域变量。看很多关于SO的帖子。这样的:
<label for="idFileUpload" class="custom-file-upload">
SelectFile
</label>
<input type="file" id="idFileUpload" nv-file-select uploader="uploader">
<label id="idSelectedFile">{{selectedFile}}</label>
<md-button id="idUploadBtn" md-no-ink class="md-primary settingsBtns" ng-click="uploader.uploadAll()" ng-disabled="!uploader.getNotUploadedItems().length">Upload</md-button>
CSS: input[type="file"] {
display: none;
}
.custom-file-upload {
background-color: green;
color: white;
border: 1px solid #ccc;
display: inline-block;
padding: 6px 12px;
cursor: pointer;
}
在FileUploader触发的事件中,您可以获取输入元素的值。HTH
- 为什么spyOn"停止函数“”的所有执行;Jasmine(要求澄清Jasmine 2.2间谍文件)
- Node.js服务器问题-已添加“/"在浏览器中查找文件时
- Django,HTML,JS:<img src=“#">可以在HTML中工作,但不能在JS文件中工作
- 在Asp.net的空网站中,如何改变"Web.config”;使内容(.js)文件显示在浏览器中,而不是下载
- "npm运行构建“;模块解析错误”;您可能需要一个适当的加载程序来处理此文件类型&”;
- Chrome、Firefox转换“:"至“-"以及“_"分别显示在文件保存对话框中
- 说明Node.js项目:是否只有一个"服务器文件“;在node.js中
- 如何在ajax中返回文本文件值Asynchronous"Synchronous正在被弃用”;
- 如何在Wordpress文件中添加自定义javascript代码"single.php”;
- 当我运行返回()时"":""Javascript中的语法,只有当我将文件保存为PHP
- MVC 4无法定位“;脚本"文件夹
- "ReferenceError未知插件“;当我尝试使用babel-cli转换目录中的js文件时
- 如何检查“;文件打开"窗口是用javascript打开的
- "不安全的JavaScript尝试访问URL为..的帧"使用本地文件
- "文件“;在mozilla扩展js模块中
- "格式不正确的JSON流”;当从SharePoint 2013 REST API对文件使用moveto或cop
- "模块化”;Javascript文件
- "在文件对话框中取消“;事件
- 正在尝试在IE7中测试HTML文件"$"是javascript部分的未定义错误
- "$(文件);在事件stopPropagation之后不触发$(a) 在“;而不触发新的元素