リンクされた要素のchildrenを反復処理するauto-carousel
ディレクティブが1つあります。
ただし、ng-if
s式はまだ解析されていないため、子はまだDOMにロードされていません。
親ディレクティブがそのDOMツリーに変更があったことを確実に確認するにはどうすればよいですか?
<ul class="unstyled" auto-carousel>
<li class="slide" ng-if="name">{{name}}</li>
...
<li class="slide" ng-if="email">{{email}}</li>
</ul>
$timeout
を使用できますが、それは信頼できないと感じています。 ng-show
の代わりにng-if
を使用することもできますが、それは質問には答えず、必要なものにも答えません。
だからここに私がやったことです:
関数を$scope.$watch
に渡すことができることを発見しました。そこから、変更を監視する式の値を返すのは非常に簡単です。これは、スコープのプロパティにキー文字列を渡すのとまったく同じように機能します。
link: function ($scope, $el, $attrs) {
$scope.$watch(
function () { return $el[0].childNodes.length; },
function (newValue, oldValue) {
if (newValue !== oldValue) {
// code goes here
}
}
);
}
childNodes
リストには要素およびが含まれているため、children
ではなくchildNodes
を監視しています。テキストノードとコメント。 Angularは、トランスクルージョンを実行してDOMを変更するng-repeat
、ng-if
、ng-switch
、およびng-include
などのディレクティブにコメントプレースホルダーを使用するため、非常に価値があります。 、children
は要素のみを保持します。
要素のdomのより深い変更を監視する必要がある場合は、MutationObserverを使用します。
.directive('myDirective', function() {
return {
...
link: function(scope, element, attrs) {
var observer = new MutationObserver(function(mutations) {
// your code here ...
});
observer.observe(element[0], {
childList: true,
subtree: true
});
}
};
});
このためのディレクティブモジュールを作成しました angular-dom-events
あなたの場合
<ul class="unstyled" auto-carousel>
<li class="slide" ng-if="name" dom-on-create="nameCreated()">{{name}}</li>
<li class="slide" ng-if="email" dom-on-destroy="emailDestroyed()">{{email}}</li>
</ul>
現在サポートしているのはdom-on-create
およびdom-on-destroy
が、$ watchコールバックを繰り返しチェックするのではなく、domイベントごとに1回だけ起動するため、受け入れられた回答よりもパフォーマンスが向上しています。
角度の推奨事項ではないと思いますが、要素の初期化時に起動するng-initを使用できます:
<ul class="unstyled" auto-carousel>
<li class="slide" ng-if="name" ng-init="recheck()">{{name}}</li>
<li class="slide" ng-if="email" ng-init="recheck()">{{email}}</li>
</ul>
最初にリンク関数内でディレクティブの内容をコンパイルしてみてください。例えば:
angular.module('myApp').directive('autoCarousel', ['$compile', function ($compile) {
return {
templateUrl: 'views/auto-carousel.html',
restrict: 'A',
replace: true,
link: function (scope, element, attr) {
$compile(element.contents())(scope);
// your code goes here
}
}
}]);