如何在AngularJS的指令模板中为ng-controller分配属性?

时间:2014-06-24 15:11:11

标签: angularjs angularjs-directive angularjs-controller angularjs-ng-include

我有一个自定义属性指令(即restrict: "A"),我想将两个表达式(使用{{...}})作为属性传递给指令。我想将这些属性传递给指令模板,我用它来渲染两个嵌套的div标记 - 外部标记包含ng-controller,内部标记包含ng-includeng-controller将定义专门用于模板的控制器,ng-include将呈现模板的HTML。

以下是显示相关摘要的示例。

HTML:

<div ng-controller="appController">
    <custom-directive ctrl="templateController" tmpl="template.html"></custom-directive>
</div>

JS:

function appController($scope) {
    // Main application controller
}

function templateController($scope) {
    // Controller (separate from main controller) for exclusive use with template
}

app.directive('customDirective', function() {
    return {
        restrict: 'A',
        scope: {
            ctrl: '@',
            tmpl: '@'
        },
        // This will work, but not what I want
        // Assigning controller explicitly
        template: '<div ng-controller="templateController">\
                       <div ng-include="tmpl"></div>\
                   </div>'
        // This is what I want, but won't work
        // Assigning controller via isolate scope variable from attribute
        /*template: '<div ng-controller="ctrl">\
                         <div ng-include="tmpl"></div>\
                     </div>'*/
    };
});

看来显式分配控制器是有效的。但是,我想通过一个隔离范围变量来分配控制器,该变量是我从位于HTML中的自定义指令内的属性获得的。

我已经在下面的Plunker中充实了上面的示例,其中列出了相关指令contentDisplay(而不是上面的customDirective)。如果这个例子需要更多评论澄清,请在评论中告诉我们:

Plunker

使用显式控制器分配(未注释的模板代码),我实现了所需的功能。但是,当尝试通过隔离范围变量(注释模板代码)分配控制器时,它不再起作用,抛出错误'ctrl' is not a function, got string

我想改变控制器的原因(而不是仅仅将所有控制器都放入一个&#34;主控制器&#34;正如我在Plunker中所做的那样)是因为我想要制作我的代码更有条理以保持可读性。

以下想法可能相关:

  • ng-controller标记放在模板中,而不是将其包裹在ng-include周围。
  • 使用单向绑定('&')执行函数而不是文本绑定('@')。
  • 使用链接功能代替/隔离范围。
  • 使用element / class指令代替属性指令。
  • ng-controller的优先级低于ng-include的优先级。
  • 编译/实例化指令的顺序可能不正确。

虽然我正在寻找这个问题的直接解决方案,但我也愿意接受能够实现相同功能且相对简单的解决方法。

1 个答案:

答案 0 :(得分:1)

我认为您不能使用template动态编写scope密钥,但您肯定会在link函数中执行此操作。您可以使用一系列内置的Angular函数非常简洁地模仿:$http$controller$compile$templateCache

Plunker

相关代码:

    link: function( scope, element, attrs )
    {
      $http.get( scope.tmpl, { cache: $templateCache } )
        .then( function( response ) {
          templateScope = scope.$new();
          templateCtrl = $controller( scope.ctrl, { $scope: templateScope } );
          element.html( response.data );
          element.children().data('$ngControllerController', templateCtrl);
          $compile( element.contents() )( templateScope );
        });
    }

受到this similar answer的强烈启发。