AngularJS mira el cambio DOM

Tengo una directiva de auto-carousel que recorre los elementos del elemento vinculado.

Sin embargo, los niños todavía no están cargados en el DOM, porque las expresiones ng-if no se han analizado todavía.

¿Cómo puedo asegurarme de que la directiva para padres sepa que ha habido cambios en su árbol DOM?

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

Podría usar $timeout pero eso no se siente confiable. También podría usar ng-show lugar de ng-if pero eso no responde la pregunta y no es lo que necesito.

Así que esto es lo que terminé haciendo:

Descubrí que podías pasar una función a $scope.$watch . A partir de ahí, es bastante sencillo devolver el valor de la expresión que desea ver para ver los cambios. Funcionará exactamente como pasar una cadena clave para una propiedad en el scope.

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

Estoy mirando childNodes , no los children , porque la lista de childNodes contiene elementos , así como nodos de texto y comentarios. Esto no tiene precio porque Angular usa marcadores de posición de comentarios para directivas como ng-repeat , ng-if , ng-switch y ng-include que realizan la transclusión y alteran el DOM, mientras que los elementos secundarios solo contienen elementos.

Si necesita observar cualquier cambio más profundo en el dom del elemento, MutationObserver es el camino 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 }); } }; }); 

Creé un módulo de directiva para este angular-dom-eventos

En tu caso podrías

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

Actualmente, solo admite dom-on-create y dom-on-destroy , pero tiene un mejor rendimiento que la respuesta aceptada, ya que solo se activará una vez por cada evento dom, en lugar de comprobar repetidamente la callback de $ watch.

Aunque no creo que sea con las recomendaciones de angular, podrías usar ng-init, que se dispara luego de la inicialización del elemento:

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

Podría tratar de comstackr los contenidos de la directiva primero dentro de su función de enlace. Por ejemplo:

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