AngularJS - 指令中的动态回调
angularjs - dynamic callback in a directive
>我正在尝试用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...
};
};
此代码应仅自定义文件类型输入的外观,并在上传文件时执行回调。
我的问题来自这样一个事实,即目前我需要使用为每个文件上传器动态构建的更改回调。如您所见,回调是使用在链接时已知的参数 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参数)。
您使用onChange: '='
和函数的方式不正确。以下解决方案确实稍微更改了指令的界面,但我认为将onChange
重命名为 onChangeFactory
可以更好地反映其预期用途。但是,如果您不介意小的不一致,则可以保留onChange
名称。
将loadFile()
自身传递为:
<xxx-file-uploader on-change-factory="loadFile(fname)" ></xxx-file-uploader>
修改指令以使用函数绑定:
scope: {
onChangeFactory: "&"
}
致电工厂并获取link()
的实际回调:
link: function(scope, element, attrs) {
// HOW ARE YOU GETTING FIELDNAME???
var onChange = scope.onChangeFactory({fname: FIELDNAME});
element.find('input[type="file"]').change(function() {
var input = this;
if (input.files && input.files[0]) {
scope.file = input.files[0];
onChange(input.files[0]); // <--- NOTE CHANGE HERE TOO
}
});
}
请注意从指令内部调用onChangeFactory()
的方式!我想会有一些空白(例如文件名),但我相信这是一个很好的起点。
如果要传入对函数的引用,则应在指令的作用域参数中使用"&"
scope: {
onChange: '&'
},
你快到了...您缺少的关键部分是$eval
。与其打电话给scope.onChangeFactory({fname: FIELDNAME});
,不如打电话:scope.$eval(scope.onChangeFactory)
。这意味着您无需知道控制器传入了什么参数。
这是我自己的代码片段,其中包含带有一些按钮的指令,并在单击按钮时添加回调。我没有使用link
而是在指令中使用controller
来响应按钮单击。
指令模板的一部分,带有可单击的按钮:
<button type='button' ng-click='incrementClick()'>
指令代码:
.directive('numberSpinner', function() {
return {
restrict: 'EA',
scope: {
onIncrement: '&'
},
controller: ['$scope', function($scope) {
$scope.incrementClick = function() {
// Evaluate the callback
$scope.$eval($scope.onIncrement);
};
}],
templateUrl: 'number-spinner.tpl.html'
};
})
使用该指令的控制器(请参阅它如何在模型对象中传递item
):
<number-spinner on-increment='myCallback(item)'></number-spinner>
在控制器中:
$scope.myCallback= function(item) {
...
};
我自己还在学习AngularJS,但这篇文章 https://stackoverflow.com/a/19890548/1959741 提到使用对象映射语法。 我在 AngularJS API 文档中找不到对象映射,但通过将 {paramName: directiveVar} 语法添加到回调事件模板中,它对我有用。
- Angular Js 尝试从主按钮回调动态更改模态文本并且不起作用
- Javascript 中的动态回调
- JQuery将字符串识别为函数动态回调
- 谷歌DFP动态广告刷新-是否有回调来确定广告是否已加载
- Javascript承诺动态回调
- 服务回调中的KendoUI网格服务器动态列绑定
- AngularJS - 指令中的动态回调
- 在回调方法中传递动态值
- _googWcmGet回调无法通过具有动态电话号码的GTM工作
- 为动态加载的javascript文件实现“错误”回调
- PassportJS - 动态设置状态以允许在回调时重定向
- ng-repeat之后的Angular JS回调是动态完成的
- 创建带有回调的动态 JSON 数组(内部闭包问题)
- 使用回调在 Chrome 中动态加载样式表
- jQueryUI对话框带有使用回调的动态按钮
- Mootools Request.JSON动态回调
- 如何在动态加载javascript文件后添加回调
- CasperJS不能正确触发动态脚本/链接调用的回调
- 动态脚本hack回调
- 如何使用PHP/JQuery/JSONP动态回调(Laravel项目)