【问题标题】:AngularJS: Transcluded content in directive disappearsAngularJS:指令中的嵌入内容消失了
【发布时间】:2016-06-02 10:28:57
【问题描述】:

我的控制器中有一个列表,ng-repeat 使用它来创建我的指令。在我的指令中,我使用嵌入来附加到指令的元素。

将第一项添加到我的列表时,它似乎按预期工作,但是当添加第二项时,嵌入的内容从第一项的元素中消失了。这对我来说毫无意义,所以我一定有什么误解。

我创建了一个example 来重现问题。

添加第一项后,html 看起来像预期的那样:

<div ng-controller="ctrl as c" class="ng-scope">
    <test ng-repeat="item in c.items track by $index" item="item" class="ng-scope ng-isolate-scope">
        <div class="ng-binding">1</div>
        <span class="ng-scope">Transcluded</span>
    </test>
</div>

添加第二项后,Transcluded的内容不再在第一项的元素中!

<div ng-controller="ctrl as c" class="ng-scope">
    <test ng-repeat="item in c.items track by $index" item="item" class="ng-scope ng-isolate-scope">
        <div class="ng-binding">1</div>
    </test>
    <test ng-repeat="item in c.items track by $index" item="item" class="ng-scope ng-isolate-scope">
        <div class="ng-binding">2</div>
        <span class="ng-scope">Transcluded</span>
    </test>
</div>

HTML:

<div ng-app="ui">
  <div ng-controller="ctrl as c">
    <test ng-repeat="item in c.items track by $index" item="item">Transcluded</test>
  </div>
</div>

打字稿:

var app = angular.module('ui', []);

class Controller {
  public items = [];

  constructor($timeout) {
    $timeout(() => this.items.push({Id: 1}), 1000);
    $timeout(() => this.items.push({Id: 2}), 2000);
  }
}
app.controller('ctrl', ['$timeout', Controller]

app.directive('test', function($compile) {
  return {
    scope: {
      item: '='
    },
    transclude: true,
    template: "<div>{{item.Id}}</div>"
    link: function(scope, element, attrs, controller, transcludeFn) {
      console.log("Appending transcluded content to " + scope.item.Id)
      let e = transcludeFn();
      element.append(e);
    }
  };
});

JSFiddle:https://jsfiddle.net/rmytw9cr/2/

【问题讨论】:

标签: angularjs angularjs-directive angularjs-ng-repeat


【解决方案1】:

除非您需要使用 transclude 功能,否则不要使用它(在 google 上查看 transclution 以获取更多信息,它有点复杂,例如您可以根据您选择的范围编译 transcluded 部分)。

您可以使用 transclude 指令进行简单的转译。

试试下面的模板,并从你的指令中移除 transclude:

template: "<div><div>{{item.Id}}</div><div ng-transclude></div></div>"

更新: 要使用嵌入功能,您需要了解它是如何工作的。 嵌入函数将回调作为第一个参数。然后,回调函数将获得转入的 html 元素作为第一个参数。

所以正确的使用方法是:

transcludeFn(function(compiledHtml) {
    // Do what ever you want with the complied HTML
    // For example: element.append(compiledHtml);
});

transclusion 函数还可以获取另一个参数,即编译 HTML 的作用域。在这种情况下,您应该提供范围作为第一个参数,并将带有编译后的 html 的回调作为第二个参数:

transcludeFn(someScope, function(compiledHtml) {
    // Do what ever you want with the complied HTML
    // For example: element.append(compiledHtml);
});

而对于final - 回调还可以得到第二个参数,即转入作用域:

transcludeFn(someScope, function(compiledHtml, transScope) {
    // Do what ever you want with the complied HTML
    // For example: element.append(compiledHtml);
    // Here transScope will be the same as someScope
});

transcludeFn(function(compiledHtml, transScope) {
    // Do what ever you want with the complied HTML
    // For example: element.append(compiledHtml);
    // Here transScope will be the same as directive scope
});

【讨论】:

  • 谢谢,这解决了我的问题。然而,我仍然很好奇为什么它没有按照我尝试的方式工作。
  • 这是因为嵌入函数的工作方式。当你调用嵌入函数时,你提供一个回调作为第一个参数,在这个回调中,第一个参数是被嵌入的元素。我会用一个例子来更新我的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-18
  • 1970-01-01
  • 2012-12-29
  • 2015-05-03
  • 2017-02-26
相关资源
最近更新 更多