Angular.js: 角床1.2.18トランスクルヌゞョンのng-repeat問題

䜜成日 2014幎06月17日  Â·  48コメント  Â·  ゜ヌス: angular/angular.js

ng-transcludeによっおディレクティブに枡す堎合、ディレクティブに実装されたng-repeat = "item incollection"を介しお繰り返したい参照{{item}}を持぀htmlコンテンツはバヌゞョン1.2.18では機胜したせん。

http://embed.plnkr.co/EvzF25sPD3uZLQivDFqy/preview

最も参考になるコメント

私がやったこずは、 $parentを䜿甚するこず

だから私は次のようなものを持っおいたす

angular.module('test').directive('myDirectiveWithTransclusion', function() {
     return {
          restrict: 'E'
          transclude: {
               transcludeThis: 'transcludeThis'
          }
          template: "<div ng-repeat='item in array'><div ng-transclude='transcludeThis'></div></div>"
     }
})
<my-directive-with-transclusion>
     <transclude-this>
          {{$parent.item}}
     </transclude-this>
</my-directive-with-transclusion>

党おのコメント48件

ああ、ロヌディ。 @petebacondarwinはこれらの別の1

倚分関連 https 

悲しいこずに、これはng-transcludeトランスクルヌゞョンが機胜する方法ではありたせん。 あなたがやろうずしおいるのは、あなた自身のディレクティブ内で䜕をスタンプアりトするかの「テンプレヌト」ずしおその子を利甚するコンテナディレクティブを䜜成するこずです。

私は過去に䜕床かこれに遭遇し、それに぀いおミスコず長い議論をしたした。 トランスクルヌゞョンされるコンテンツは、定矩䞊、ディレクティブがむンスタンス化される堎所のスコヌプにバむンドされたす。 ディレクティブのテンプレヌトの範囲ではありたせん。

以前は、ネストされたトランスクルヌゞョンシナリオが関係する堎合に、実際にトランスクルヌゞョンを間違ったスコヌプにバむンドしおいたため、これは機胜しおいた可胜性がありたす。

したがっお、実際にここでトランスクルヌゞョンを䜿甚する必芁はありたせん。実際に実行しようずしおいるのは、内郚HTMLを独自のテンプレヌトに挿入するこずだけだからです。 これは、次のようなコンパむル関数で実行できたす。

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

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

  return {
    restrict: 'E',
    compile: function compile(tElement, tAttrs, tTransclude) {

      // Extract the children from this instance of the directive
      var children = tElement.children();

      // Wrap the chidren in our template
      var template = angular.element('<div ng-repeat="item in collection"></div>');
      template.append(children);

      // Append this new template to our compile element
      tElement.html('');
      tElement.append(template);

      return {
        pre: function preLink(scope, iElement, iAttrs, crtl, transclude) {
            scope.collection = [1, 2, 3, 4, 5];
        },
        post: function postLink(scope, iElement, iAttrs, controller) {
          console.log(iElement[0]);
        }
      };
    }
  };
});

これの別の䟋私は信じおいたす

Index.html

<html ng-app='myApp'>

<head>
    <title>AngularJS Scopes</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
    <script src='index.js'></script>
</head>

<body ng-controller='myController'>
    <people>Hello {{person.name}}</people>
</body>
</html>

index.js

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

myApp.controller( 'myController', function( $scope ) {
    $scope.people = [
        { name: 'Rob'  },
        { name: 'Alex' },
        { name: 'John' }
    ];
});

myApp.directive( 'people', function() {
    return {
        restrict: 'E',

        transclude: true,
        template: '<div ng-repeat="person in people" ng-transclude></div>',
    }
});

Angular 1.2.1で動䜜したしたが、1.2.18では動䜜したせんでした。

眪のない開発者は、䞊蚘のコヌドが機胜するこずしか期埅できたせんでした。 このドキュメントには次のように曞かれおいたす。

...文字列やオブゞェクトではなく、テンプレヌト党䜓を枡すこずができるこずが望たしい堎合がありたす。 「ダむアログボックス」コンポヌネントを䜜成するずしたす。 ダむアログボックスは、任意のコンテンツを折り返すこずができる必芁がありたす。

ngTranscludeのドキュメントには次のように曞かれおいたす。

トランスクルヌゞョンを䜿甚する最も近い芪ディレクティブのトランスクルヌゞョンされたDOMの挿入ポむントをマヌクするディレクティブ。 このディレクティブが配眮されおいる芁玠の既存のコンテンツは、トランスクルヌゞョンされたコンテンツが挿入される前に削陀されたす。

これは@petebacondarwinの定矩ずどのように異なりたすか

...独自のディレクティブ内でスタンプアりトするものの「テンプレヌト」ずしおその子を利甚するコンテナディレクティブを䜜成したす

トランスクルヌゞョンがここで正しい解決策ではない理由を私は本圓に理解しおいたせん。 どちらかずいえば、合理的な解決策には、テンプレヌトスコヌプをトランスクルヌゞョン関数に挿入するこずが含たれるず思いたす。

違いは、トランスクルヌゞョンされたコンテンツが「倖郚」、぀たり<people>芁玠が芋぀かる堎所のスコヌプにバむンドされるこずです。
䞀方、必芁なのは、むンラむンテンプレヌトを「内郚」、぀たりディレクティブのスコヌプにバむンドするこずです。
ディレクティブが独自のスコヌプを䜜成しない堎合、これはほが同じです。 たずえば、ディレクティブが分離スコヌプを䜜成する堎合、それは間違いなく同じこずではありたせん。 内偎のスコヌプは倖偎のスコヌプにアクセスできたせん。

テンプレヌトスコヌプをトランスクルヌゞョン関数に実際に挿入する独自のディレクティブを䜜成できるず思いたす...

http://plnkr.co/edit/IbNqR0854V8yXnajKSFB?p=previewを参照しおください

あなたが蚀っおいるこずは完党に理にかなっおいたす-しかしそれはあなたがAngularの深さを理解しおいる堎合にのみです。 私のポむントは、䞊蚘の䟋は、あたり䜙分な䜜業をしなくおも、どういうわけか機胜するはずだずいうこずです。

トランスクルヌゞョン関数が䜕らかの方法でテンプレヌトたたは「内郚」スコヌプにアクセスできるようにするこずは、私には非垞に合理的で非垞に実甚的であるように思われたす。 なぜこれが必芁になるのか、倚くの堎合考えられたす。

たったく同じ問題がこのブログで説明され

そしお、コヌドをどうもありがずう。 私は他の人の利益のためにここでそれを耇補しおいたす

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

myApp.controller( 'myController', function( $scope ) {
    $scope.people = [
        { name: 'Rob'  },
        { name: 'Alex' },
        { name: 'John' }
    ];
});

myApp.directive( 'people', function() {
    return {
        restrict: 'E',
        transclude: true,
        template: '<div ng-repeat="person in people" inject></div>'
    }
});

myApp.directive('inject', function(){
  return {
    link: function($scope, $element, $attrs, controller, $transclude) {
      if (!$transclude) {
        throw minErr('ngTransclude')('orphan',
         'Illegal use of ngTransclude directive in the template! ' +
         'No parent directive that requires a transclusion found. ' +
         'Element: {0}',
         startingTag($element));
      }
      var innerScope = $scope.$new();
      $transclude(innerScope, function(clone) {
        $element.empty();
        $element.append(clone);
        $element.on('$destroy', function() {
          innerScope.$destroy();
        });
      });
    }
  };
});

:-)私は、トランスクルヌゞョンは、頭をかいたり、キヌボヌドを叩いたりしない限り、理解しやすいトピックではないこずに同意したす。
おそらく、ng-transcludeがトランスクルヌゞョンされたコンテンツを「倖郚」スコヌプにバむンドするずいう事実に぀いお、ドキュメントをさらに明確にする必芁がありたすか

個人的には、少なくずもこの重芁なペヌゞにある珟圚のドキュメントは、かなり明確で明確だず思い

このトランスクルヌゞョンオプションは正確に䜕をしたすか transcludeは、このオプションを䜿甚しおディレクティブのコンテンツが、ディレクティブの内郚ではなく倖郚のスコヌプにアクセスできるようにしたす。

そしお、以䞋のすべおがこれをさらに説明したす。

おそらくあなたがフレヌムワヌクに提䟛したディレクティブを远加しお、おそらくそれを「ng-transclude-internal」ずブランド化するこずを怜蚎したすか 「transcope」ず呌ばれるディレクティブを䜿甚しお、これに挑戊した人が少なくずももう1人いるこずを私は知っおいたす。

私は解決策を詊したしたが、他の問題に盎面したした。なぜng-repeatの芪スコヌプがディレクティブのスコヌプではないのですか

http://plnkr.co/edit/7j92IC?p=preview

@luboidプランカヌで機胜しない理由は、ディレクティブに分離スコヌプがあり、倉曎されたコンパむル枈みDOMちなみに、これはこの問題を解決するためのばかげた方法ですを䜿甚するためです。分離スコヌプの芪の兄匟。

それを期埅どおりに機胜させるための適切な方法の䟋を远加したす。 しかし、これはただ䞀般的にかなりひどいデザむンであり、これを行う正圓な理由はありたせん

実際、考えおみるず、ng-repeatやその他の芁玠トランスクルヌゞョンディレクティブでは、これを実際に修正するこずはできたせん。 そうそう、バヌゞョン1.2.0以降は機胜したせん

@petebacondarwinここに本圓に初心者の質問がありたす。 単にの代わりにvar innerScope䜿甚する理由

myApp.directive( 'inject', function() {
    return {
        link: function( $scope, $element, $attrs, controller, $transclude ) {
            if ( !$transclude ) {
                throw minErr( 'ngTransclude' )( 'orphan',
                    'Illegal use of ngTransclude directive in the template! ' +
                    'No parent directive that requires a transclusion found. ' +
                    'Element: {0}',
                    startingTag( $element ));
            }

            $transclude( $scope, function( clone ) {
                $element.empty();
                $element.append( clone );
            });
        }
    };
}); 

元のディレクティブがスコヌプなども䜜成したい耇雑なディレクティブず䜵眮されおいるかどうかわからないため、新しい芁玠をコンパむルする堎合は、通垞、新しいスコヌプを䜜成するのが最適です。ただし、取埗できる堎合がありたす。ここでそれを離れお...

手䌝っおくれおありがずう、
倖郚テンプレヌト$ templateCacheを䜿甚したす。その埌、少し単玔になりたす。基本テンプレヌトはディレクティブスコヌプでコンパむルされたす。

@ Izhaki @ petebacondarwinむンクルヌドディレクティブをありがずうございたす。 ぀いに1.2.16から1.2.20に曎新されたしたが、アプリが非垞に壊れ始めた理由を確認するのに少し時間がかかりたした。

このスレッドを芋぀ける前は、トランスクルヌゞョンは非垞に単玔な抂念だず思っおいたした。 いいえ。

これを解決するのを手䌝っおくれたすべおの人に感謝したす。 1.2.21に曎新するず、ここで説明する問題のためにむンタヌフェむスの倚くが壊れ、珟圚は正しい方向に進んでいたす。

@caitp @petebacondarwin 2぀の远加情報を取埗できれば非垞に圹立ちたす。

  1. 「バヌゞョン1.2.0に぀いお」ケむトリンが蚀ったようにどこかで起こったどの重倧な倉曎が、このアプロヌチを突然爆発させたのでしょうか 䜕が機胜しなくなったかは理解しおいたすが、そのリリヌスの近くの倉曎ログに、この特定の問題に関連しおいるず思われる特定のものは芋圓たりたせん。
  2. 任意の内郚コンテンツを継承できる分離された再利甚可胜なコンテナが必芁な堎合、゚ンドナヌザヌがng-transcludeの代わりに採甚する必芁がある代替アプロヌチは䜕ですか 䟋倧芏暡なマルチテナントアプリケヌション。むンタヌフェむスも可倉で、完党にデヌタ駆動型です。 そのため、リストコントロヌルのように、デヌタを取埗しおデヌタを入力し、䞀貫した盞互䜜甚/動䜜を行う必芁があるものがありたす。 それらを提䟛するラッパヌディレクティブを暙準化できるようにしたいず考えおいたす。 ただし、リストアむテムに䜿甚するテンプレヌト内郚ディレクティブが含たれおいる堎合がありたすは、状況によっお異なりたす。 たた、リストは、それらを生成するデヌタのツリヌ構造に基づいお、再垰的にネストされるこずがよくありたす。 したがっお、これらのネストされたリストを分離する必芁がありたす。 すべおのコヌドを制埡するため、内郚を倖郚から分離するためにトランスクルヌゞョンを䜿甚しおいたせん。 むしろ、ディレクティブガむドで明瀺的に掚奚されおいるように、コンテナずその任意のコンテンツに察する優れた宣蚀型アプロヌチの盎埌です。 ng-includeは、むンラむンテンプレヌトから離れお、少し慣甚的ではないず感じたすが、これにはより良いオプションが含たれおいたすかコンテナ宣蚀の属性ずしお内郚テンプレヌトぞのパスを枡したす

䜕が機胜しなくなったかは理解しおいたすが、そのリリヌスの近くの倉曎ログに、この特定の問題に関連しおいるず思われる特定のものは芋圓たりたせん。

https://github.com/angular/angular.js/blob/master/CHANGELOG.md#120 -timely-delivery-2013-11-08

私は特にこれらに蚀及しおいたした

  • 分離ディレクティブd0efd5eeに属する子にのみ分離スコヌプを枡したす
  • 分離スコヌプを真に分離する909cabd3、1924、2500

でも、ボຈل͜ຈを知っおいる、もう䜕を話しおいたのか、本圓に思い出せたせん。

倉曎ログには、倉曎ず重倧な倉曎の2皮類のメッセヌゞしかありたせん。 これは重倧な倉曎ではなく、バグ修正ず芋なされおいたした。 倚くの人がこの動䜜を䜿甚したこずを予枬するこずは困難でした。 しかし、それはおそらく移行ドキュメントに入るはずですそれはいく぀かの愛が必芁です

翔 ''ナフ。 それらはそれらです。 トランスクルヌゞョンに関連する倉曎を探しおいたしたが、これは明らかに、トランスクルヌゞョンに付随する分離スコヌプの倉曎です。 ありがずう

この倉曎により、コヌドも砎損したした。 これらのディレクティブのperson倉数にアクセスし、それらを芪スコヌプで䜿甚するための簡単な宣蚀型の方法があるずbugが1.2.18で修正される前に䜕人の人がそれを䜿甚しおいたかを芋るず、これは䞀般的な䜿甚䟋のようです。

これは1.2.17で動䜜し、1.2.18以降で壊れたデモです。

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

@evgenyneu 内郚コンテンツずコンテナディレクティブの䞡方を制埡するず仮定するず、トランスクルヌゞョンの代わりにng-includeを䜿甚するこずは明確で簡単であり、必芁な継承パタヌンが埗られるこずがわかりたした。 テンプレヌト名を倖郚ディレクティブ宣蚀の属性ずしお枡すだけで、以前にtranscludeディレクティブがあったのず同じ堎所にng-includeディレクティブを配眮したす。 問題が解決したした。

内郚コンテンツテンプレヌトをビュヌテンプレヌト䞊でむンラむンにしたい堎合は、ng-templateを䜿甚しお、以前䜿甚しおいたのず同じ䜍眮にテンプレヌトをラップしたす。

@xmlilley 、すばらしいヒント、どうもありがずうございたした。 それは確かに最もクリヌンなアプロヌチです。

デモは次のずおりです http 

http://plnkr.co/edit/fw7thti1u4F9ArxsuYkQ?p=preview ---完璧ではありたせんが、そこに到達したす。

@caitp 、いいね、ありがずう。 私たちはたくさんの解決策を持っおいたす

この問題を芋おいる人のために、私は「改善された」ng-transcludeディレクティブを䜜成したした。その属性倀は、求められる内郚スコヌプを定矩し、3のいずれかになりたす。

  • シルビング-トランスクルヌゞョンされたコンテンツスコヌプは、トランスクルヌゞョンが発生する芁玠の兄匟スコヌプです。 これが珟圚のng-transcludeの動䜜です。
  • 芪-トランスクルヌゞョンされたコンテンツスコヌプは、トランスクルヌゞョンが発生する芁玠のスコヌプです。
  • 子䟛は-トランスクルヌド内容の範囲は、トランスクルヌが発生した芁玠のスコヌプの子スコヌプです。

䜿甚䟋

template: 
  '<div ng-transclude="parent">' +
  '</div>'

完党な䟋

すべおの䟋に぀いおは、このプランクを参照しおください。

出力は次のようになりたす。

image

゜ヌス

.config(function($provide){
    $provide.decorator('ngTranscludeDirective', ['$delegate', function($delegate) {
        // Remove the original directive
        $delegate.shift();
        return $delegate;
    }]);
})

.directive( 'ngTransclude', function() {
  return {
    restrict: 'EAC',
    link: function( $scope, $element, $attrs, controller, $transclude ) {
      if (!$transclude) {
        throw minErr('ngTransclude')('orphan',
         'Illegal use of ngTransclude directive in the template! ' +
         'No parent directive that requires a transclusion found. ' +
         'Element: {0}',
         startingTag($element));
      }

      var iScopeType = $attrs['ngTransclude'] || 'sibling';

      switch ( iScopeType ) {
        case 'sibling':
          $transclude( function( clone ) {
            $element.empty();
            $element.append( clone );
          });
          break;
        case 'parent':
          $transclude( $scope, function( clone ) {
            $element.empty();
            $element.append( clone );
          });
          break;
        case 'child':
          var iChildScope = $scope.$new();
          $transclude( iChildScope, function( clone ) {
            $element.empty();
            $element.append( clone );
            $element.on( '$destroy', function() {
              iChildScope.$destroy();
            });            
          });
          break;
      }
    }
  }
})

@ Izhaki -FWIW、+ 10。 珟圚の芏則に違反したせんが、䞀般的なナヌスケヌスに自発的にアクセスするためのクリヌンで宣蚀的な方法を远加したす。 ありがずう

+1 @Izhakiの゜リュヌション甚。 これをそのたた䜿甚したすが、angularに含めるずはるかに快適になりたす。

+1

@Izhaki +1、玠晎らしい䟋です

カスタムトランスクルヌゞョンディレクティブをありがずう。 デフォルトを䞊曞きするのではなく、別のカスタムトランスクルヌゞョンを䜜成するこずになりたした。 パッチには、どこから来たのかわからない関数呌び出しがいく぀かありたす。 minErrおよびstartingTag

@ dehru-これらの関数はAngularJSの内郚にありたす。

@Izhakiどうもありがずう 興味があれば、トランスクルヌゞョンされたコンテンツを繰り返すあなたのプランクをフォヌクしたした。
ng-transclude = "parent"が期埅どおりに機胜しない可胜性があるこずに泚意しおください。
http://plnkr.co/edit/S6ngqz?p=preview

plunker_ng-transclude_ng-repeat

@Izhakiずおもいい。
角床ぞのプルリク゚ストに含たれるべきもののように芋えたす。
少なくずもGithubリポゞトリを䜿甚した別のディレクティブでは、公開できるず思いたすか倉曎を提䟛できるように...
ありがずう

むザキ、これはすごい。 私はあなたを_心_したす。

@Izhakiこれは、子スコヌプの問題に察する非垞に優れた゜リュヌションです。 ありがずう。

しかし、私は混乱しおいお、$ transclude関数の継承が倖郚ディレクティブからngTranscludeディレクティブにどのように䌝わるのか説明できるかどうか疑問に思っおいたしたか 私が芋぀けるこずができる公匏の堎所はどこにも明瀺されおいたせんが、リンク関数で$ transclude関数を䜿甚するには、ディレクティブでtransclude: trueを䜿甚する必芁があるず思いたした。 コヌドを少し詊しおみたずころ、 transclude: true実際にコヌドが壊れおいるこずがわかりたした。 䜕が起きおる

私はこれず䜕日も戊っただけでなく、トランスクルヌゞョンがトランスクルヌゞョンされた芁玠をそれらに眮き換えるのではなく、トランスクルヌゞョンプレヌスホルダヌ内に挿入するずいう事実もありたした。

ng-transclude-replaceが䞡方の問題を凊理するこずがわかりたした http://gogoout.github.io/angular-directives-utils/#/api/ng -directives-utils.transcludeReplace

ng-repeatディレクティブをrepeatedディレクティブ自䜓たたはそのようなものに䌝播する必芁はありたせん すべおの怜蚌/バむンディングを含め、すべおが機胜しおいるように芋えたす。

これが私のコヌドのスニペットです

<form-field label="Roles" required>
    <checkbox-group>
        <checkbox ng-repeat="role in roles" label="{{role.description}}">
            <input type="checkbox" name="selectedRoles" ng-model="role.selected" value="{{role.description}}" ng-required="!hasRole" />
        </checkbox>
    </checkbox-group>
</form-field>

@abobwhite ng-

私は最近この問題に遭遇したした。 @Izhakiは私のために働いおいたしたが、この議論からの間にベストプラクティスが出珟したかどうか興味がありたす。 特に、 ng-transclude="sibling | parent | child"を角床コアの䞀郚にするこずに関心はありたしたか

@ telekid-珟圚、この機胜をコアに含める予定はありたせん。

解決策ず回避策があるず思いたすが、ディレクティブの内郚スコヌプにアクセスする方法があれば非垞に䟿利です。

@Izhakiが䜜成したおきたす。
ブランチ https 
PR https 
プランカヌ http //plnkr.co/edit/5XGBEX0muH9CSijMfWsHp = Preview

私がやったこずは、 $parentを䜿甚するこず

だから私は次のようなものを持っおいたす

angular.module('test').directive('myDirectiveWithTransclusion', function() {
     return {
          restrict: 'E'
          transclude: {
               transcludeThis: 'transcludeThis'
          }
          template: "<div ng-repeat='item in array'><div ng-transclude='transcludeThis'></div></div>"
     }
})
<my-directive-with-transclusion>
     <transclude-this>
          {{$parent.item}}
     </transclude-this>
</my-directive-with-transclusion>

こんにちは@ moneytree-doug私はあなたが提䟛したこの゜リュヌションを䜿甚したすが、トランスクルヌゞョンのスコヌプを芋぀けたした-これはただディレクティブスコヌプであり、ng-repeatによっお生成される新しいスコヌプの子ではありたせん。 いく぀か提案をいただけたすか

@szetin䜕が起こっおいるのか、䜕を期埅しおいるのかを瀺すjsfiddleを䜜成しおいただけたせんか。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡