我正在尝试使用 angularjs 创建一个指令,但我发现了一个问题。
这是指令的js代码
angular.module('xxxFileUploader', [])
.directive('xxxFileUploader', function() {
return {
restrict: 'E',
templateUrl: 'fileUploader.html',
scope: {
onChange: '='
},
link: function(scope, element, attrs) {
element.find('input[type="file"]').change(function() {
var input = this;
if (input.files && input.files[0]) {
scope.file = input.files[0];
scope.onChange(input.files[0]);
});
}
};
});
指令模板
<span style="position:relative;">
<a class='btn btn-primary' href='javascript:;'>
Choose File...
</a>
<input type="file"
name="{{field.name}}"
style='position:absolute;z-index:2;top:0;left:0;filter: alpha(opacity=0);opacity:0;background-color:transparent;color:transparent;'
/>
<span class='label label-info'>{{file.name}}</span>
</span>
我在其中使用指令的一段 html 文件
<xxx-file-uploader on-change="loadFile(field.name)" ></xxx-file-uploader>
和我的控制器的相关部分
$scope.loadFile = function(fieldName) {
return function(file) {
// do things with both fieldName and file...
};
};
此代码应该只自定义文件类型输入的外观并在上传文件时执行回调。
我的问题来自这样一个事实,即目前我需要使用为每个 fileUploader 动态构建的更改回调。如您所见,回调是使用在链接时已知的参数 fieldName 和在“执行时”已知的参数文件构建的。
使用此代码,我得到 AngularJS “错误:达到 10 个 $digest() 迭代。流产!” 因为(我认为)该函数一次又一次地生成,而摘要不匹配。
一个穷人的解决方案是将 fieldName 作为另一个范围变量传递。另一个可能是将函数作为字符串 (@) 传递并在我需要时构建回调。
关于如何在不更改其界面的情况下使该指令工作的任何建议?我对 angularjs 指令很陌生(这是我的第一个指令!)所以如果您在代码中发现任何错误,请指出。
谢谢你。
第一次编辑:
我试图按照我的建议更改指令的范围
scope: {
onChange: '='
},
至
scope: {
onChange: '&'
},
我改变了回调调用
scope.onChange(input.files[0]);
至
scope.onChange()(input.files[0]);
现在它可以工作了,但我对结果并不完全满意。
看起来需要调用 onChange 函数来获取我的“真实”回调。在这种情况下,有没有办法让它隐式执行?
我的意思是,如果我写
<xxx-file-uploader on-change="loadFile(field.name)" ></xxx-file-uploader>
它应该理解执行该功能
如果相反我写
<xxx-file-uploader on-change="doSomething" ></xxx-file-uploader>
它应该认识到 doSomething 是我希望它执行的“真实”回调(使用 file 参数)。