Come posso eseguire una direttiva dopo che il dom ha finito il rendering?

Ho un problema apparentemente semplice senza soluzione apparente (leggendo la documentazione di Angular JS) .

Ho una direttiva Angular JS che esegue alcuni calcoli basati sull’altezza di altri elementi DOM per definire l’altezza di un contenitore nel DOM.

Qualcosa di simile a questo sta succedendo all’interno della direttiva:

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

Il problema è che quando viene eseguita la direttiva, $('site-header') non può essere trovata, restituendo una matrice vuota invece dell’elemento DOM jQuery che ho bisogno di wrapping.

C’è un callback che posso usare all’interno della mia direttiva che viene eseguito solo dopo che il DOM è stato caricato e posso accedere ad altri elementi DOM tramite le normali query di stile del selettore jQuery?

Dipende da come viene costruito $ (‘site-header’).

Puoi provare a utilizzare $ timeout con 0 ritardo. Qualcosa di simile a:

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

Spiegazioni su come funziona: uno , due .

Non dimenticare di inserire il $timeout nella tua direttiva:

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

Ecco come lo faccio:

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

Probabilmente l’autore non avrà più bisogno della mia risposta. Tuttavia, per completezza, sento che altri utenti potrebbero trovarlo utile. La soluzione migliore e più semplice è usare $(window).load() all’interno del corpo della funzione restituita. (in alternativa puoi usare document.ready . Dipende davvero se hai bisogno di tutte le immagini o meno).

L’utilizzo del $timeout a mio modesto parere è un’opzione molto debole e potrebbe non riuscire in alcuni casi.

Ecco il codice completo che userei:

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

c’è un evento ngcontentloaded , penso che tu possa 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) } } }); 

Se non è ansible utilizzare $ timeout a causa di risorse esterne e non è ansible utilizzare una direttiva a causa di un problema specifico con i tempi, utilizzare broadcast.

Aggiungi $scope.$broadcast("variable_name_here"); dopo il completamento della risorsa esterna desiderata o del controller / direttiva di lunga durata.

Quindi aggiungere il seguente dopo aver caricato la risorsa esterna.

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

Ad esempio nella promise di una richiesta HTTP differita.

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

Ho avuto un problema simile e voglio condividere la mia soluzione qui.

Ho il seguente codice HTML:

 

Problema: nella funzione link della direttiva del genitore div volevo jquery’ing il div figlio sub. Ma mi ha appena dato un object vuoto perché ng-include non era finito quando funzionava la funzione di collegamento della direttiva. Quindi, per prima cosa ho risolto il problema con timeout $, che ha funzionato, ma il parametro delay dipendeva dalla velocità del client (a nessuno piace).

Funziona ma sporco:

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

Ecco la soluzione pulita:

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

Forse aiuta qualcuno.