2013-04-18 14 views
6

上のトランスクルーで複数のディレクティブ私は要素に2つのテンプレートを注入し、それらを操作しようとしている:AngularJS:同じ要素

<div 
    ic-first="foo" 
    ic-second="bar" 
    ic-third="baz" 
    ic-fourth="qux" 
> 
</div> 

icFirstはの子としてテンプレートを経由して、空のdivを注入すべきですその要素。 icSecondは、その要素の第2の子として(コンテンツの束を有する)第二のdivを注入しなければならないので、結果のHTMLは次のようになり:

<div 
    ic-first="foo" // priority: 100 
    ic-second="bar" // priority: 50 
    ic-third="baz" // priority: 0 
    ic-fourth="qux" // priority: 0 
> 
    <div id="foo"></div> 
    <div> <!-- a bunch of stuff from the templateUrl --> </div> 
</div> 

両方icFirsticSecondは、他の要素を注入します新たに作成されたコンテナに追加します。

私は両方のディレクティブに関する指令テンプレートプロパティを指定すると、私はエラーを取得する:私は両方のディレクティブにtransclude: trueを追加すると

Error: Multiple directives [icFirst, icSecond] asking for template on: <div ic-first

icFirstがうまく実行される...しかし、同じで、他のディレクティブ要素は実行されません。 transclude: 'element'を設定すると、他のディレクティブでが実行されますが、になると、最初の子($scope.firstObj)が定義されていないというエラーが表示されます。

すべての4つのディレクティブは、お互いのスコープにアクセスする必要があるので、私は自分のコントローラに私の仕事のほとんどをやってる:

app.directive('icFirst', ['ic.config', function (icConfig) { 
    return { 
    restrict: 'A', 
    priority: 100, 
    template: '<div id="{{firstId}}"></div>', 
    replace: false, 
    transclude: 'element', 
    controller: function icFirst($scope, $element, $attrs) { 
     // … 
     $scope.firstId = $scope.opts.fooId; 
     $scope.firstElm = $element.children()[0]; 
     $scope.firstObj = {}; // this is used by the other 3 directives 
    }, 
    link: function(scope, elm, attrs) { … } // <- event binding 
    } 
); 
app.directive('icSecond', ['ic.config', function (icConfig) { 
    return { 
    restrict: 'A', 
    priority: 0, 
    templateUrl: 'views/foo.html', 
    replace: false, 
    transclude: 'element', 
    controller: function icSecond($scope, $element, $attrs) { 
     // … 
     $scope.secondElm = $element.children()[1]; 
     $scope.secondObj = new Bar($scope.firstObj); 
     //^is used by the remaining 2 directives & requires obj from icFirst 
    }, 
    link: function(scope, elm, attrs) { … } // <- event binding 
    } 
); 

私は文書化行動を一致させるためにreplace: falseの動作を修正し、プルリクエスト#2433に記載されているように。

コントローラー内で$scope.firstObjのインスタンスを作成し、linkFnに設定しました(linkFnが実行されるまでにトランジションが完了することを期待していました)が、同じ問題が発生します。最初の子は実際にはコメントであるようです。私は、このエラーを投げ説明を考え出すことができる

答えて

1

唯一の理由はAngularJSチームは言うまでもない上書き/ DOM操作を避けるためにしようとしていたということです。文書化行動対replace: falseの実際の行動を考慮し

、私は思います実際は実際には意図された動作です。これが当てはまる場合、複数のtemplates/templateUrlを同じ要素で使用できるようにすると、それ以降のテンプレートは以前のテンプレートを上書きします。

Iはすでに†クイックフィックスとして、私は(angular.js:4624に相当)assertNoDuplicateチェックを除去する(/src/ng/compile.js:700)再度ソースを変更し、文書化挙動と一致するようにソースを変更しているので。今私は、次の2つのオブジェクトを返し、それが動作し、私は、任意の負の影響を見つけることができません:永久的なものならば、チェックはおそらく
if (directive.templateUrl && directive.replace)
(とについても同様である必要があり

// directive icFirst 
return { 
    restrict: 'A', 
    priority: 100, 
    replace: false, 
    template: '<div id="{{firstId}}"></div>', 
    require: ["icFirst"], 
    controller: Controller, 
    link: postLink 
}; 
// directive icSecond 
return { 
    restrict: 'A', 
    require: ['icFirst'], 
    replace: false, 
    templateUrl: 'views/bar.html', 
    priority: 50, 
    controller: Controller, 
    link: postLink 
}; 

をdirective.template)

+2

ここでは簡単な方法があります。あなたのディレクティブに '$$ tlb:true'を追加すれば、それはアサーションをバイパスします。 –

+1

@JonathanRowny '$$'は、 '$$ tlb'がAPIに対して「プライベート」であることを示しています。開発者はAPIの外では使用しないでください。 –

関連する問題