AngularJS 带有 ng-include 和单独模板指令的动态模板

AngularJS dynamic template with ng-include and separate template directives

我想创建一个 div,它根据上下文参数动态加载不同的模板:

我的 "search-results-container" 指令:

app.directive("searchResultsContainer", function() {
  restrict: "E",
  templateUrl: "search-results-container.html",
  controller: function($scope) {
    $scope.templates = [
      { viewmode: "list", url: "search-results-list-view.html" },
      { viewmode: "grid", url: "search-results-grid-view.html" },
      { viewmode: "table", url: "search-results-table-view.html" }
    ]
  },
  link: function(scope) {
    scope.toggleView = function() {
      scope.templates.push(scope.templates.shift());
    }
  }
}

我的 "search-results-container.html" 文件:

<div ng-include="templates[0].url"></div>

我的 "search-results-table-view.html" 文件:

<table>
  <tr ng-repeat="item in ctrl.items">
    <td>{{ item.title }}</td>
  <tr>
</table>

动态加载模板没有问题。 但是,我希望这些模板在完成加载后 运行 具有一些 "callback" 功能。

我知道有 "onload" 属性,我可以这样添加它:

<div ng-include="templates[0].url" onload="onLoadFunction()"></div>

这意味着我需要在范围内用 "onLoadFunction" 填充我原来的 "search-results-container" 指令,这将不得不使用开关(或类似技术)来区分模板文件和运行 特定功能取决于当前活动的功能 - 我想阻止它,因为它不干净。

我想为每个模板设置单独的指令,例如:

app.directive("searchResultsTableView", function() {
    return {
        restrict: "E",
        templateUrl: "search-results-table-view.html",
        controller: function($scope) {
            ...
        },
        link: function(scope) {
          scope.someOnLoadFunction = function() {
            /* Stuff to execute when template has loaded */
          }
        }
    }
});

如果我这样做,我会相应地更改我的 "search-results-table-view.html":

<search-results-table-view>
  <table>
    <tr ng-repeat="item in ctrl.items">
      <td>{{ item.title }}</td>
    <tr>
  </table>
</search-results-table-view>

...我 运行 进入某种无限循环之类的,然后 Angular / 浏览器崩溃(变得无响应)。有没有一种方法可以实现我的计划,而无需使用大量 "onLoad" 函数填充容器的指令,每个嵌套模板一个?

我们最终做的是这样的:

我们有一个指令:

app.directive("searchResultsContainer", function() {
  restrict: "E",
  templateUrl: "search-results-container.html",
  controller: function($scope) {
    $scope.templates = [
      { viewmode: "list", url: "search-results-list-view.html" },
      { viewmode: "grid", url: "search-results-grid-view.html" },
      { viewmode: "table", url: "search-results-table-view.html" }
    ]
  },
  link: function(scope) {
    scope.toggleView = function() {
      scope.templates.push(scope.templates.shift());
    }
  }
}

该指令是使用 ng-include 指令实例化的:

<search-results-container ng-include="views/result-list.html"></search-results-container>

使用的结果-list.html文件有这段话:

<div ng-switch on="templates[0].viewmode">
    <search-results-list-view ng-switch-default></gs-search-results-list-view>
    <search-results-grid-view ng-switch-when="grid"></gs-search-results-grid-view>
    <search-results-table-view ng-switch-when="table"></gs-search-results-table-view>
</div>

它有一个按钮可以在视图之间切换,使用一个简单的 ng-click 指令:

<button ng-click="toggleViewMode()">Toggle View</button>

此按钮触发上面指令中描述的 searchResultsContainer 的 toggleView 方法,移动模板数组的元素:

scope.toggleView = function() {
    scope.templates.push(scope.templates.shift());
}

ng-switch 指令侦听模板数组第一个元素的 "viewmode" 属性 中的变化:

ng-switch on="templates[0].viewmode" 

点击按钮时会发生这种变化,从而完全改变数组中的第一个元素,这自然也会导致 "viewmode" 属性 的变化,由 ng-switch 监控。

嵌套的 ng-switch-default 和 ng-switch-when 指令对更改做出反应并显示相应的元素,该元素在 "ng-switch-when" 中设置了适当的值。

ng-switch 的三个子项各自使用一个单独的指令,这是其中之一:

app.directive("searchResultsListView", function() {
    return {
        restrict: "E",
        require: "^searchResultsContainer",
        template: "<div ng-include=\"'views/list-view.html'\"></div>",
        controller: function($scope) {
            /* $scope stuff goes here */
        },
        link: function(scope, element, attrs, searchResultsCtrl) {
            /* link stuff goes here */
        }
    }
});

请注意模板的 ng-include 指令中非常重要的转义引号,后跟高位逗号,这是 ng-include 指令所要求的 (more info on ng-include)。