AngularJS Template替换指令不起作用

时间:2015-01-13 13:07:07

标签: angularjs templates angularjs-directive angularjs-compile

我有一个模板指令几乎按照我想要的方式工作,简单版本有效: -

<div bw-template-replace>
  <template>This is template text, replace [[#this]] please</template>
  <this>text replaced</this>
</div>

扩展为

<div bw-template-replace><span>This is template text, replace text replaced please</span></div>

但是,如果我嵌入其他指令,它们就不能完全按预期工作。

请参阅我的plunk http://plnkr.co/edit/dLUU2CMtuN5WMZlEScQi?p=preview

在指令的链接函数的末尾,我编译生成的文本/节点,该文本/节点适用于{{范围内插文本}},但不适用于使用相同范围的嵌入式指令。

我需要这个的原因是因为我正在使用ng-translate来存在现有的ng-app,我想使用现有的英文文本作为翻译查找的键。一个不常见的翻译案例是我们有以下HTML(从应用程序中提取),[[#ageInput]]和[[#agePeriod]]&#39;参数&#39;可能出现在其他语言的不同地方,据我所知,ng-translate目前对此方案没有真正的支持。

<div class="row-fluid">
    <div class="span12" translate bw-template-replace>
        <template>
            If current version of media has not been read for [[#ageInput]] [[#agePeriod]]
        </template>
        <ageInput><input type=number ng-model="policy.age" style="width:50px"/></ageInput>
        <agePeriod><select style="width:100px" ng-model="policy.period" ng-options="p for p in periods" /></agePeriod>
    </div>
</div>

任何帮助都非常感激。

我喜欢在你成为新手的时候通过这些场景,因为它真的迫使你去了解发生了什么。我现在有它工作,基本上我以前的指令我发现几种方法只是替换html希望Angular会神奇地排序所有东西。现在我对翻译有了更好的理解,特别是我使其按预期工作的翻译功能。传递到$ transcludeFn的克隆元素已经附加了范围并且已经编译了$,因此我的函数现在解析模板文本并生成单独的textElement并移动参数元素以适应模板。

  

我当前的解决方案

.directive('TemplateReplace', ['$compile', '$document', '$timeout',
  function ($compile, $document, $timeout) {
      return {
          restrict: 'AC',
          transclude: true,
          link: function (scope, iElement, iAttrs, controller, transclude) {
              transclude(scope, function (clone, $scope) {
                  $timeout(function () {
                      // Our template is the first real child element (nodeType 1)
                      var template = null;
                      for (var i = 0, ii = clone.length; i < ii; i++) {
                          if (clone[i].nodeType == 1) {
                              template = angular.element(clone[i]);
                              break;
                          }
                      }

                      // Remember the template's text, then transclude it and empty its contents
                      var html = angular.copy(template.text());
                      iElement.append(template);        // Transcluding keeps external directives intact
                      template.empty();                 // We can populate its inards from scratch

                      // Split the html into pieces seperated by [[#tagname]] parts
                      if (html) {
                          var htmlLen = html.length;

                          var textStart = 0;
                          while (textStart < htmlLen) {
                              var tagName = null,
                                tagEnd = htmlLen,
                                textEnd = htmlLen;

                              var tagStart = html.indexOf("[[#", textStart);
                              if (tagStart >= 0) {
                                  tagEnd = html.indexOf("]]", tagStart);
                                  if (tagEnd >= 0) {
                                      tagName = html.substr(tagStart + 3, tagEnd - tagStart - 3);
                                      tagEnd += 2;
                                      textEnd = tagStart;
                                  }
                              }

                              // Text parts have to be created, $compiled and appended
                              var text = html.substr(textStart, textEnd - textStart);
                              if (text.length) {
                                  var textNode = $document[0].createTextNode(text);
                                  template.append($compile(textNode)($scope));
                              }

                              // Tag parts are located in the clone then transclude appended to keep external directives intact (note each tagNode can only be referenced once)
                              if (tagName && tagName.length) {
                                  var tagNode = clone.filter(tagName);
                                  if (tagNode.length) {
                                      template.append(tagNode);
                                  }
                              }
                              textStart = tagEnd;
                          }
                      }
                  }, 0);
              });
          }
      };
  }
]);

1 个答案:

答案 0 :(得分:1)

如果我已正确理解你的问题,我想问题是你的指令是在ng-repeat准备dom之前执行的。所以你需要在$timeout中进行DOM操作。

检查此plunker以获取工作示例。

以下是对类似问题的一个很好的解释:https://stackoverflow.com/a/24638881/3292746