使用name属性

时间:2015-12-22 08:05:20

标签: javascript angularjs

我试图用动态控制器实现指令,以便我可以根据某些条件绑定控制器,就像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>

它给出了这样的错误:

  

参数不是函数,未定义

我有什么想法可以解决这个问题?还是其他任何方式? 谢谢!

1 个答案:

答案 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