簡體   English   中英

Angularjs:嵌入指令模板

[英]Angularjs: transclude directive template

在以下情況下如何使用嵌入。 目的是在 html(部分)文件中使用標記,而不是在模板中(在指令內)定義它。

我在這里找到了一個很棒的樹指令。 來源)原文: http : //jsfiddle.net/n8dPm/

我沒有在指令中定義模板,而是嘗試使用嵌入的內容。 我還將 Angular 更新為 1.2.0.rc2。 更新: http : //jsfiddle.net/aZx7B/2/

得到以下錯誤

類型錯誤:對象 [object Object] 的屬性“$transclude”不是函數

代碼:

module.directive("tree", function($compile) {
    return {
        restrict: "E",
        transclude: true,
        scope: {family: '='},
        template:       
            '<ul>' + 
                '<li ng-transclude></li>' +
                '<li ng-repeat="child in family.children">' +
                    '<tree family="child"></tree>' +
                '</li>' +
            '</ul>',
        compile: function(tElement, tAttr) {
            var contents = tElement.contents().remove();
            var compiledContents;
            return function(scope, iElement, iAttr) {
                if(!compiledContents) {
                    compiledContents = $compile(contents);
                }
                compiledContents(scope, function(clone, scope) {
                         iElement.append(clone); 
                });
            };
        }
    };
});

<div ng-app="myapp">
    <div ng-controller="TreeCtrl">
        <tree family="family">
            <p>{{ family.name }}</p>
        </tree>
    </div>
</div>

編輯:

在大衛的建議下,做了一些改動。 http://jsfiddle.net/aZx7B/3/現在,它打印,父。 改變, family -> treeFamily雖然不起作用

您還需要在模板中輸出家庭的名稱: http : //jsfiddle.net/roadprophet/DsvX6/

module.directive("tree", function($compile) {
    return {
        restrict: "E",
        transclude: true,
        scope: {family: '='},
        template:       
            '<ul>' + 
                '<li ng-transclude></li>' +
                '<li ng-repeat="child in family.children">' +
                    '<tree family="child">{{family.name}}</tree>' +
                '</li>' +
            '</ul>',
        compile: function(tElement, tAttr, transclude) {
            var contents = tElement.contents().remove();
            var compiledContents;
            return function(scope, iElement, iAttr) {
                if(!compiledContents) {
                    compiledContents = $compile(contents, transclude);
                }
                compiledContents(scope, function(clone, scope) {
                         iElement.append(clone); 
                });
            };
        }
    };
});

編輯

你也可以通過這樣做來簡化: http : //jsfiddle.net/roadprophet/DsvX6/2/

<div ng-app="myapp">
    <div ng-controller="TreeCtrl">
        <tree family="treeFamily">           
        </tree>
    </div>
</div>


module.directive("tree", function($compile) {
    return {
        restrict: "E",
        transclude: true,
        scope: {family: '='},
        template:       
            '<ul>' + 
                '<li ng-transclude></li>' +
                '<p>{{ family.name }}</p>' + 
                '<li ng-repeat="child in family.children">' +
                    '<tree family="child"></tree>' +
                '</li>' +
            '</ul>',
        compile: function(tElement, tAttr, transclude) {
            var contents = tElement.contents().remove();
            var compiledContents;
            return function(scope, iElement, iAttr) {
                if(!compiledContents) {
                    compiledContents = $compile(contents, transclude);
                }
                compiledContents(scope, function(clone, scope) {
                         iElement.append(clone); 
                });
            };
        }
    };
});

編輯雖然問題的來源相同。 沒有模板被傳遞給內部樹指令。 http://jsfiddle.net/roadprophet/DsvX6/3/

<div ng-app="myapp">
    <div ng-controller="TreeCtrl">
        <tree family="treeFamily">           
                <p>{{ family.name }}</p>
        </tree>
    </div>
</div>

 template:       
            '<ul>' + 
                '<li ng-transclude></li>' +
                '<li ng-repeat="child in family.children">' +
                    '<tree family="child"><div ng-transclude></div></tree>' +
                '</li>' +
            '</ul>'

您想針對作用域編譯嵌入的 DOM; 您可以使用指令的控制器定義中的可注入$transclude函數自動執行此操作:

module.directive("tree", function($compile) {
  return {
    restrict: "E",
    transclude: true,
    scope: { family: '=' },
    template: '<ul>' + 
                '<li ng-repeat="child in family.children">' +
                  '<tree family="child">' +
                    '<p>{{ child.name }}</p>' +
                  '</tree>' +
                '</li>' +
              '</ul>',
    controller: function($element, $transclude) {
      $transclude(function(e) {
        $element.append(e);
      });
    },
    compile: function(tElement, tAttr, transclude) {
      var contents = tElement.contents().remove();
      var compiledContents;
      return function(scope, iElement, iAttr) {
        if(!compiledContents) {
          compiledContents = $compile(contents);
        }
        compiledContents(scope, function(clone) {
          iElement.append(clone);
        });
      };
    }
  };
});

這允許您在根模板中使用作用域屬性treeFamily (還要注意上面指令模板中child的使用):

<div ng-app="myapp">
  <div ng-controller="TreeCtrl">
    <tree family="treeFamily">
      <p>{{ treeFamily.name }}</p>
    </tree>
  </div>
</div>

你可以在這里看到一個例子: http : //jsfiddle.net/BinaryMuse/UzHeW/

晚會很晚了。 我在一個項目中需要這個,所以在深入研究並找到其他很好的方法和方向之后,終於想出了這個:

ng-transclude指令相同的代碼,但添加了少量context綁定,該指令在每次更改時監視和設置嵌入生成的范圍。 ng-repeat相同,但這允許:

  1. 使用自定義的 ng-transclude 和 ng-repeat 沒有重寫 ng-repeat 的麻煩,就像 angular/2 模板出口。
  2. 讓嵌入的內容在從父級接收直接上下文數據的同時保持訪問祖父級范圍。 再次與模板插座相同。

增強的 ng-transclude 函數:

return function ngTranscludePostLink(
   ...
  ) {
  let context = null;
  let childScope = null;
  ...
  $scope.$watch($attrs.context, (newVal, oldVal) => {
    context = newVal;
    updateScope(childScope, context);
  });
  ...
  $transclude(ngTranscludeCloneAttachFn, null, slotName);
  ...
  function ngTranscludeCloneAttachFn(clone, transcludedScope) {
     ...                                 
     $element.append(clone);
     childScope = transcludedScope;
     updateScope(childScope, context);
     ...
  }
  ...
  function updateScope(scope, varsHash) {
    if (!scope || !varsHash) {
      return;
    }
    angular.extend(scope, varsHash);
  }
}

它的用法是:

應用程序

<my-list items="$ctrl.movies">
   <div>App data: {{ $ctrl.header }}</div>
   <div>Name:{{ name }} Year: {{ year }} Rating: {{ rating 
          }}</div>
</my-list>

我的列表

<ul>
  <li ng-repeat="item in $ctrl.items track by item.id">
   <div>Ng repeat item scope id: {{ $id }}</div>
   <cr-transclude context="item"></cr-transclude>
  </li>
</ul>

完整的指令代碼可以在 GitHub 上找到

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM