AngularJS assiste a mudança DOM

Eu tenho uma diretiva auto-carousel que percorre os filhos do elemento vinculado.

No entanto, os filhos ainda não estão carregados no DOM, porque suas expressões ng-if ainda não foram analisadas.

Como posso ter certeza de que a diretiva pai sabe que houve alterações em sua tree DOM?

  
  • {{name}}
  • ...
  • {{email}}

Eu poderia usar $timeout mas isso não é confiável. Eu também poderia usar ng-show vez de ng-if mas isso não responde a pergunta e não o que eu preciso.

Então aqui está o que acabei fazendo:

Eu descobri que você poderia passar uma function para $scope.$watch . A partir daí, é bastante simples retornar o valor da expressão que você deseja observar para as alterações. Ele funcionará exatamente como passar uma string de chave para uma propriedade no escopo.

 link: function ($scope, $el, $attrs) { $scope.$watch( function () { return $el[0].childNodes.length; }, function (newValue, oldValue) { if (newValue !== oldValue) { // code goes here } } ); } 

Eu estou assistindo childNodes , não children , porque a lista childNodes contém elementos , bem como nós de texto e comentários. Isso é inestimável porque o Angular usa espaços reservados para comentários para diretivas como ng-repeat , ng-if , ng-switch e ng-include que realizam a transclusão e alteram o DOM, enquanto que as children possuem apenas elementos.

Se você precisa observar quaisquer mudanças mais profundas no dom do elemento, o MutationObserver é o caminho a seguir:

 .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 }); } }; }); 

Eu criei um módulo de diretiva para esses events angular-dom

No seu caso, você poderia

  
  • {{name}}
  • {{email}}

Atualmente, apenas suporta dom-on-create e dom-on-destroy , mas tem melhor desempenho do que a resposta aceita, porque será acionado apenas uma vez para cada evento dom, em vez de verificar repetidamente o retorno de chamada $ watch.

Embora eu não ache que é com as recomendações do angular, você poderia usar o ng-init que é acionado na boot do elemento:

 
  • {{name}}
  • {{email}}

Você pode tentar compilar o conteúdo da diretiva primeiro dentro da sua function de link. Por exemplo:

 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 } } }]); 
Intereting Posts