¿Cómo puedo ejecutar una directiva después de que dom termine de renderizar?

Tengo un problema aparentemente simple sin aparente (al leer la documentación de Angular JS docs) .

Tengo una directiva Angular JS que hace algunos cálculos basados ​​en la altura de otros elementos DOM para definir la altura de un contenedor en el DOM.

Algo similar a esto está sucediendo dentro de la directiva:

return function(scope, element, attrs) { $('.main').height( $('.site-header').height() - $('.site-footer').height() ); } 

El problema es que cuando se ejecuta la directiva, no se puede encontrar $('site-header') , devolviendo una matriz vacía en lugar del elemento DOM envuelto jQuery que necesito.

¿Existe una callback que pueda usar dentro de mi directiva que solo se ejecute después de que se haya cargado DOM y pueda acceder a otros elementos DOM a través de las consultas normales del estilo del selector jQuery?

Depende de cómo se construya su $ (‘site-header’).

Puede intentar usar $ timeout con 0 delay. Algo como:

 return function(scope, element, attrs) { $timeout(function(){ $('.main').height( $('.site-header').height() - $('.site-footer').height() ); }); } 

Explicaciones de cómo funciona: uno , dos .

No olvides incluir $timeout en tu directiva:

 .directive('sticky', function($timeout) 

Así es como lo hago:

 app.directive('example', function() { return function(scope, element, attrs) { angular.element(document).ready(function() { //MANIPULATE THE DOM }); }; }); 

Probablemente el autor ya no necesitará mi respuesta. Sin embargo, para completar, creo que otros usuarios pueden encontrarlo útil. La mejor y más simple solución es usar $(window).load() dentro del cuerpo de la función devuelta. (alternativamente puede usar document.ready . Realmente depende si necesita todas las imágenes o no).

Usar $timeout en mi humilde opinión es una opción muy débil y puede fallar en algunos casos.

Aquí está el código completo que usaría:

 .directive('directiveExample', function(){ return { restrict: 'A', link: function($scope, $elem, attrs){ $(window).load(function() { //...JS here... }); } } }); 

hay un evento ngcontentloaded , creo que puedes usarlo

 .directive('directiveExample', function(){ return { restrict: 'A', link: function(scope, elem, attrs){ $$window = $ $window init = function(){ contentHeight = elem.outerHeight() //do the things } $$window.on('ngcontentloaded',init) } } }); 

Si no puede usar $ timeout debido a recursos externos y no puede usar una directiva debido a un problema específico con el tiempo, use broadcast.

Agregue $scope.$broadcast("variable_name_here"); después de que se haya completado el recurso externo deseado o el controlador / directiva de larga duración.

A continuación, agregue lo siguiente una vez que haya cargado su recurso externo.

 $scope.$on("variable_name_here", function(){ // DOM manipulation here jQuery('selector').height(); } 

Por ejemplo, en la promesa de una solicitud HTTP diferida.

 MyHttpService.then(function(data){ $scope.MyHttpReturnedImage = data.image; $scope.$broadcast("imageLoaded"); }); $scope.$on("imageLoaded", function(){ jQuery('img').height(80).width(80); } 

Tuve un problema similar y quiero compartir mi solución aquí.

Tengo el siguiente HTML:

 

Problema: en la función link de la directiva del div principal, quise jquery’ing el div div secundario. Pero solo me dio un objeto vacío porque ng-include no había terminado cuando se ejecutó la función de enlace de la directiva. Así que primero hice una solución sucia con $ timeout, que funcionó pero el parámetro de demora dependía de la velocidad del cliente (a nadie le gusta eso).

Funciona pero sucio

 app.directive('myDirective', [function () { var directive = {}; directive.link = function (scope, element, attrs) { $timeout(function() { //very dirty cause of client-depending varying delay time $('#sub').css(/*whatever*/); }, 350); }; return directive; }]); 

Aquí está la solución limpia:

 app.directive('myDirective', [function () { var directive = {}; directive.link = function (scope, element, attrs) { scope.$on('$includeContentLoaded', function() { //just happens in the moment when ng-included finished $('#sub').css(/*whatever*/); }; }; return directive; }]); 

Quizás ayuda a alguien.