AngularJS指令 - 可以在postLink后调用“模板”函数。

时间:2014-11-24 23:50:46

标签: angularjs angularjs-directive angularjs-compile

解释起来很复杂,但我会尝试。

http://plnkr.co/edit/PrVXRvHAC7wtgHUEU1HB?p=preview

此示例的工作原理是,因为我需要,我只是不喜欢我实现此目的的方式。

我将尝试解释您在示例中看到的内容。

<repeater>

  <item name="Hello item">
    <h4>Hello</h4>
    <p>Lorem ipsum dolor sit amet</p>
  </item>

  <item name="Worlditem">
    <h4>World</h4>
    <em>Mauris elementum elementum enim at suscipit.</em>
  </item>

</repeater>

<item>指令应将自己“注册”为父repeater available_item。现在不应该显示它。

<repeater>指令应打印可用项目菜单,点击菜单项后,应将项目模板添加到其内容中。例如,repeater模板可能如下所示:

<div>
  <ul>
    <li ng-repeat="item in available_items">
      <a href="javscript:;" ng-click="add2content(item)">{{item}}</a>
    </li>
  </ul>

  <div id="content">
    <div ng-repeat="item in content_items track by $index">
      <ng-include src="item"></ng-include>
    </div>
  </div>

</div>

那么在我的工作 plnkr.co示例中我不喜欢什么?

我不喜欢我必须<div ng-transclude></div>中包含repeater.html,否则<item>将不再编译。但我不需要在页面加载时打印项目 - 它们只是模板。我已将<items>模板设置为空字符串,但在源代码中我看到空<item>个标签,我不喜欢这个...

实际上我不确定我不喜欢那里,但感觉就像hard-coded一样,不是吗?

如果repeater的指令按此顺序编译:

  1. controller() - add2available()函数将被注册
  2. preLink()
  3. //现在转到所有item指令,他们可以将自己注册到转发器
  4. postLink()
  5. template() - 现在转发器更改了模板,其中没有ng-transclude
  6. 我敢肯定这是不可能做到的。而且我不确定我的代码中我不喜欢什么,但我希望您会看到其他方法来改进我的代码。

    非常感谢!

    P.S。我知道我可以使用<item>个标记替换<script type="text/ng-template" id="">指令,但我需要<item>,如我的示例所示。

1 个答案:

答案 0 :(得分:1)

除了您不喜欢的部分(即虚拟<transclude>标记和空<item>标记)之外,此plunkr执行您想要实现的目标。我还清理了黑客,比如在属性中存储HTML,返回空模板,污染模板缓存......

此解决方案的关键元素是使用$transclude服务来编译和链接在已转换内容中声明的指令。整个更新的脚本如下。

<强>的script.js

angular.module('repeaterApp', [])
  .directive('repeater', function() {
    return {
      restrict: 'E',
      transclude: true,
      scope: {},
      templateUrl: 'repeater.html',
      controller: function($scope, $element, $transclude) {
        var available_items = $scope.available_items = [];
        var content_items = $scope.content_items = [];

        $scope.add2content = function(item) {
          content_items.push(item);
        };

        $scope.add2available = function(item) {
          available_items.push(item);
        };

        $transclude($scope);
      }
    };
  })
  .directive('item', function($templateCache, $sce) {
    return {
      restrict: 'E',
      link: function(scope, element, attrs) {
        scope.add2available({
          name: element.attr('name'),
          html: $sce.trustAsHtml(element.html())
        });
      }
    };
  });

<强> repeater.html

<div>
  <ul>
    <li ng-repeat="item in available_items">
      <a href="javscript:;" ng-click="add2content(item)">{{item.name}}</a>
    </li>
  </ul>

  <div id="content">
    <div ng-repeat="item in content_items track by $index" 
         style="background: #f4f4f4; padding: 5px; margin: 5px; clear: both;"
         ng-bind-html="item.html">
    </div>
  </div>
</div>

<强>的index.html

<repeater>

  <item name="Hello item">
    <h4>Hello</h4>
    <p>Lorem ipsum dolor sit amet</p>
  </item>

  <item name="Worlditem">
    <h4>World</h4>
    <em>Mauris elementum elementum enim at suscipit.</em>
  </item>

</repeater>