在AngularJS的ng-repeat指令中动态显示模板?

11

我希望动态地在ng-repeat指令中根据当前项显示多个模板之一。

我的JSON数据如下:

data: {
    groups: [
        {
            name: "Group 1",                
            sections: [
                { name: "Section A" },
                { name: "Section B" }
            ]
        },
        {
            name: "Group 2",                
            sections: [
                { name: "Section A" },
                { name: "Section B" }
            ]
        }
    ]
}

我的目标是动态渲染数据树,每个分组包含多个小节。所有分组将具有相同的模板,但每个小节应基于名称字段具有自己的模板。

假设顶层HTML是:

<div ng-repeat="group in groups">
    {{ group.name }}
    <div ng-repeat="section in sections">
        <!-- Dynamic section template used -->
    </div>
</div>

理想情况下,每个部分也需要有自己的作用域数据和控制器。我使用Knockout构建这种类型系统时效果很好,但我正在尝试了解Angular的工作方式。


听起来像是指令的一个好案例。 - lucuma
Lucuma,你能再多评论一下吗?我也考虑过使用指令,但不确定理想的粒度级别。我应该构建一个仅执行模板选择的指令,还是每个“部分”都应该有自己的指令? - Brian Vallelunga
我认为这取决于你想如何制作它。你可以创建一个指令来完成所有操作(传递组数组),或者你可以创建另一个指令,在你的组指令内部调用它来处理各个部分。指令的好处是它们拥有自己的作用域。我将提供一个小例子。 - lucuma
2个回答

34
你可以这样做:

您可以采取以下方式:

<div ng-repeat="group in groups">
    {{ group.name }}
    <div ng-repeat="section in sections" ng-include="getIncludeFile(section)">
        <!-- Dynamic section template used -->
    </div>
</div>

然后在你的控制器中:

$scope.getIncludeFile = function(section) {
    // Make this more dynamic, but you get the idea
    switch (section) {
        case "Section A":
            return 'partials/sectiona.html';
        case "Section B":
            return 'partials/sectionb.html';
    }
}

那么你的sectiona.html文件可能像这样(为了使控制器专门针对该文件):

<div ng-controller="SectionAController">
    <!-- HTML in here, and can bind straight to your SectionAController -->
</div>

这是目前我使用的最直接的方法。如果我的需求变得更加复杂,我可能会采用指令方法。 - Brian Vallelunga
如果我想将JSON项转换为链接列表,并路由到新页面,怎么办?所有这些页面都将遵循相同的模板,具有像帖子类型之类的独特属性...但我不需要数据库或管理员。只需要为每个数据项创建一个新页面,使用相同的视图模板即可。 - Omar

4
在过去的一个月中,Angular引入了一个检查支持指令中动态模板的功能。然而,我并没有找到很多关于它使用的信息。以下是参考文献:https://github.com/angular/angular.js/pull/1849 虽然这仍然使用相同的nginclude,但所有内容都封装在两个指令中:
演示:http://plnkr.co/edit/4DIlHMNlHQ8Wm9XHNycH?p=preview HTML:
<groups-control groupdata="groups"></groups-control>

控制器:

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
  var json = {data: {
    groups: [
        {
            name: "Group 1",                
            sections: [
                { name: "Section A" },
                { name: "Section B" }
            ]
        },
        {
            name: "Group 2",                
            sections: [
                { name: "Section A" },
                { name: "Section B" }
            ]
        }
    ]
  }};
  $scope.groups = json.data.groups;

}); 

指令分为两部分:

app.directive('groupsControl', function(){
    return {
      restrict: 'E',

      replace: true,
      transclude: false,
      scope: { items:'=groupdata'},

      template: '<div ng-repeat="group in items">' +
                  '{{ group.name }}' +
                  '<section-control sections="group.sections" />'+

              '</div>',
      // The linking function will add behavior to the template
      link: function(scope, element, attrs) {


      }
    }
  }).directive('sectionControl', function(){
    return {
      restrict: 'E',

      replace: true,
      transclude: false,
      scope: { items:'=sections'},

      template: '<div ng-repeat="section in items" ng-include="getIncludeFile(section)">'+
                '</div>',

      link: function(scope, element, attrs) {
        scope.getIncludeFile = function(section) {
            return section.name.toLowerCase().replace('section ','') + ".html";
        }

      }
    }
  });

我希望能看到有人发布一篇使用函数基于一些范围数据来确定templateUrl的答案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接