在自定义指令中,如何在生成模板之前执行逻辑?

时间:2015-11-20 19:55:11

标签: javascript angularjs frontend directive

我想编写一个带有字符串数组的自定义指令,并将其呈现为如下所示的表:

'string1'  | 'string2'  | 'string3'  | 'string4'
'string5'  | 'string6'  | 'string7'  | 'string8'
'string9'  | 'string10' | 'string11' | 'string12'

它应该像这样使用:

<div class="my-directive" values="values" rowsize="4"></div>

我认为实现这一目标的合适策略是首先将values拆分为大小为rowsize的数组。然后,使用内部ng-repeat呈现ng-repeat。所以指令的输出DOM看起来像这样:

<table>
    <tr ng-repeat="part in parts">
        <td ng-repeat="value in part">
            {{value}}
        </td>
    </tr>
</table>

这意味着在指令中我需要首先做一些逻辑(将数组拆分成更小的数组),然后使用ng-repeat ,如上所示。

这个指令也可以使用手动DOM操作器编写,但我想以Angular的方式做事:)

所以,问题是:在自定义指令中,我怎样才能先做一些逻辑(通常在link函数中完成),然后生成一个模板(通常放在template属性中)?

1 个答案:

答案 0 :(得分:1)

这应该可以解决问题:http://plnkr.co/edit/UYMQtMuZeJRcSQynHUGW?p=info

基本上,我们需要动态创建包含项目数组的行对象。如果我们没有达到允许列的最大数量,我们只想添加到这个项目数组中,这是通过maxColumns传递给指令的任何内容所指定的:

正如您将通过plunker看到的那样,您可以修改HTML中的max-columns属性,并且该指令应该适当地绘制:

app.controller('MainCtrl', function($scope) {
  $scope.values = [
    'string1','string2','string3','string4','string5','string6',
    'string7','string8','string9','string10','string11','string12'
  ];
});

app.directive('myTable', function() {

  var templateHtml = 
      '<table border="1">' +
          '<tr ng-repeat="row in rows">' + 
              '<td ng-repeat="item in row.items">{{item}}</td>' +
          '</tr>' + 
      '</table>';

  return {
    restrict: 'E',
    template: templateHtml,
    scope: {
      values: '=',
      maxColumns: '@'
    },
    link: function(scope, element, attrs) {

        scope.rows = [];
        scope.rows.push(_getNewRow())

        function _getNewRow() {
          return { items: [] };
        }

        _.each(scope.values, function(value) {
            currentRow = _.last(scope.rows);
            if (currentRow.items.length < scope.maxColumns) {
               currentRow.items.push(value);
            } else {
               currentRow = _getNewRow();
               currentRow.items.push(value);
               scope.rows.push(currentRow);
            }
        });

    }
  }
});