に頼るつもりなので、これは簡単ではありませんng-bind-html
。
最初にこれを見てみましょう:
transclude(scope, function(clone, scope){
panelCtrl.setBody($sce.trustAsHtml(clone.html()));
});
上記clone
の関数には、次のような子panel
ディレクティブのコメント プレースホルダーが含まれます。
One Body
<!-- panel: undefined -->
これは、子パネル ディレクティブに がtransclude: 'element'
あり、そのリンク関数がまだ実行されていないためです。
これを修正するのは簡単です。コードを少し変更するだけです。
var clone = transclude(scope, function () {});
panelCtrl.setBody($sce.trustAsHtml(clone.html()));
このようにして、clone
次のような実際のテンプレートが含まれます。
One Body
<div class="ng-scope"><h1 class="ng-binding">{{panel.title}}</h1><div class="inner ng-binding" ng-bind-html="panel.body"></div></div>
それほど驚くことではありませんが、実際のテンプレートができましたが、バインディングはまだ行われていないためclone.html()
、現時点ではまだ使用できません。
そして、本当の問題が始まります:バインディングがいつ終了するかをどうやって知ることができますか?
私の知る限り、正確な時期はわかりません。しかし、これを回避するには、$timeout
!
を使用することにより$timeout
、通常のコンパイル サイクルが中断されるため、子ディレクティブのバインディングが完了したことを親パネル ディレクティブに知らせる何らかの方法を見つける必要があります ( $timeout
)。
1 つの方法は、通信にコントローラーを使用することで、最終的なコードは次のようになります。
app.controller('PanelCtrl', function($scope, $sce) {
$scope.panel = {
title: 'ttt',
body: $sce.trustAsHtml('bbb'),
}
this.setTitle = function(title) {
$scope.panel.title = title;
};
this.setBody = function(body) {
$scope.panel.body = body;
};
var parentCtrl,
onChildRenderedCallback,
childCount = 0;
this.onChildRendered = function(callback) {
onChildRenderedCallback = function () {
callback();
if (parentCtrl) {
$timeout(parentCtrl.notify, 0);
}
};
if (!childCount) {
$timeout(onChildRenderedCallback, 0);
}
};
this.notify = function() {
childCount--;
if (childCount === 0 && onChildRenderedCallback) {
onChildRenderedCallback();
}
};
this.addChild = function() {
childCount++;
};
this.setParent = function (value) {
parentCtrl = value;
parentCtrl.addChild(this);
};
});
app.directive('panel', function($compile, $sce, $timeout) {
return {
restrict: 'E',
scope: {},
replace: true,
transclude: 'element',
controller: 'PanelCtrl',
require: ['panel', '?^panel'],
link: function(scope, element, attrs, ctrls, transclude) {
var panelCtrl = ctrls[0];
var parentCtrl = ctrls[1];
if (parentCtrl) {
panelCtrl.setParent(parentCtrl);
}
var template =
'<div>' +
' <h1>{{panel.title}}</h1>' +
' <div class="inner" ng-bind-html="panel.body"></div>' +
'</div>';
var templateContents = angular.element(template);
var compileTemplateContents = $compile(templateContents);
element.replaceWith(templateContents);
panelCtrl.setTitle(attrs.title);
var clone = transclude(scope, function () {});
panelCtrl.onChildRendered(function() {
panelCtrl.setBody($sce.trustAsHtml(clone.html()));
compileTemplateContents(scope);
});
}
}
});
プランカーの例: http://plnkr.co/edit/BBbWsUkkebgXiAdcnoYE?p=preview
plunker に多くのものを残しましたconsole.log()
。実際に何が起こっているかを確認できます。
PS。ng-bind-html
使用せずに DOM 操作を許可するか、@WilliamScott の回答のようなものを使用すると、作業がはるかに簡単になります。