我试图用动态控制器实现指令,以便我可以根据某些条件绑定控制器,就像Todd Motto已经显示它here
一切正常,期望我不能将对象属性作为名称发送到指令,例如,
<directive-with-dynamic-controller ctrl="someObj.prop"></directive-with-dynamic-controller>
我甚至试过这个,但无济于事:
<directive-with-dynamic-controller ctrl="{{someObj.prop}}"></directive-with-dynamic-controller>
它给出了这样的错误:
参数不是函数,未定义
我有什么想法可以解决这个问题?还是其他任何方式? 谢谢!
答案 0 :(得分:2)
我有什么想法可以解决这个问题?还是其他任何方式?谢谢!
问题在于执行顺序。在上面提到的文章中遗漏的一点是,在设置“动态”控制器的情况下,无法传递表达式(对动态来说太多了)。
如果我们查看指令 compile 步骤的符号,您会注意到没有访问当前$scope
。
这是因为DOM编译和控制器初始化发生在之前角度解析器启动并评估您的表达式。
因此,无法将$ scope表达式传递给ctrl
属性,因为此时它只是一个常规DOM属性。实质上,您将原始字符串传递给ctrl
属性。
<my-custom-dir ctrl="foo.bar"></my-custom-dir>
// Error: "foo.bar" is not a controller // is not a function // $minErrObscureStuffThatDoesnHelpYou.
我一直试图找出一种灵活的方式让deferred directive compilation现在运行一段时间,但无济于事......
解决此问题的一种可能方式( ymmv ):
.directive('...', function ($controller) {
controller: function ($scope, $element, $attrs) {
$attrs.$observe('ctrl', function (n, o) {
return $controller(n, {
$scope: $scope,
$element: $element,
$attrs: $attrs
});
});
}
});
实际上,您将替换预先初始化的控制器(无效),控制器与您通过attrs.ctrl
属性传递的名称相匹配。但是,这将执行后编译 - 所以我不会认真推荐它。
jsfiddle showing the order of execution
tl; dr 目前还没有基于$ scope表达式为指令定义控制器的灵巧方法。它必须是一个原始字符串,因为编译不是基于每个组件的范围,而是以“全局”执行顺序更多。
DOM编译&gt;控制器初始化&gt;范围链接fiddle