2012-08-14 3 views
28

Comment exécuter une méthode $scope.myWork() après le modèle de rendu? Je veux placer le $scope.value et après que je dois changer quelque chose avec JQuery (par exemple dans DOM du contenu de modèle). $scope.$watch('value', function(){....}) fonctionne "avant" rendre (DOM du modèle n'est pas encore disponible). Merci.AngularJS: rappel après rendu (travail avec DOM après rendu)

Répondre

20

Créez un directive qui exécute votre code dans la fonction de lien. La fonction de liaison est appelée après la construction du modèle.

Voir ng-click pour avoir une idée.

+0

Il est mon exemple, cela ne fonctionne pas - http://jsfiddle.net/C6SUv/7/ (pourquoi n » t $ scope.afterRender appeler après chaque rendu?). – user1595465

+0

parce que la fonction de lien est appelée une fois après que l'élément est rendu, et non après chaque rendu angulaire. Pourquoi vous ne pouvez pas créer des directives faites les changements dont vous avez besoin avec jQuery et mettre à jour angulaire? Manipuler DOM à l'intérieur des contrôleurs n'est pas une bonne pratique –

+0

Hmmmmm. Je dois faire défiler div avec la hauteur fixe. J'ai des boutons pour déplacer le curseur dans la liste des champs. J'ai mis $ scope.value dans ngClick et après je dois faire défiler la bonne position (via scrollTop). C'est la raison pour laquelle je veux manipuler avec DOM à l'intérieur du contrôleur. Une idée? – user1595465

15

J'utilise terminal et transclude dans une directive d'attribut pour appeler une méthode scope après un modèle est mis à jour et la vue est rendue (dans mon cas pour redimensionner un iframe après une Resource.query $):

.directive('postRender', [ '$timeout', function($timeout) { 
var def = { 
    restrict : 'A', 
    terminal : true, 
    transclude : true, 
    link : function(scope, element, attrs) { 
     $timeout(scope.resize, 0); //Calling a scoped method 
    } 
}; 
return def; 
}]) 

Le $ timeout est de la magie noire. Il devrait être possible de déclarer la méthode JS comme valeur d'attribut et $ l'analyser.

Je l'utilise dans un ng-repeat (dans mon cas, un arbre est rendu récursive):

<div post-render ng-repeat="r in regions | orderBy:'name'" ng-include="'tree_region_renderer.html'"> 
2

Jens réponse fonctionnera ci-dessus, mais notez que sur les nouvelles versions de AngularJS (par exemple 1.2.3) vous ne peut pas avoir cette directive postRender en combinaison avec ng-repeat en tant qu'attributs sur le même tag car ils ont tous les deux transclude: true. Dans ce cas, vous devez soit supprimer transclude ou avoir une balise distincte avec l'attribut de la directive postRender.
Soyez également attentif à la priorité des attributs lors de l'utilisation du terminal: true car vous pourriez finir par avoir un attribut non efficace en raison d'un attribut priorotorisé supérieur sur le même tag.

7

J'ai aussi eu ce problème, d'autres solutions ne fonctionnaient pas bien pour moi, et cela semblait être le genre de chose que Protractor devait résoudre. Un examen rapide de Protractor's client-side scripts montre qu'il utilise angular.getTestability(element) pour savoir quand exécuter réellement les tests. La méthode attend jusqu'à ce qu'il n'y ait plus de délai d'attente ou de requête HTTP, puis exécute votre rappel. Voici ma directive:

export function afterRender ($timeout) { 
"ngInject"; 
    return { 
     restrict: 'A', 
     terminal: true, 
     link: function (scope, element, attrs) { 
     angular.getTestability(element).whenStable(function() { 
      console.log('[rendered]'); 
     }); 
     } 
    }; 
} 
+1

Depuis que vous utilisez l'application Angular, vous pouvez simplement injecter '$ browser' et enregistrer un callback avec sa méthode' notifyWhenNoOutstandingRequests() '. Notez cependant que cela dépend de certaines API privées non documentées et que celles-ci peuvent être interrompues sans préavis. – gkalpak

-2

J'ai trouvé cette page lorsque je cherchais un moyen de profiler le rendu DOM. J'ai trouvé une solution très simple qui fonctionne pour mon cas d'utilisation.

Attachez un gestionnaire ng-init à l'élément DOM et à la fonction gestionnaire, utilisez $ timeout pour obtenir l'exécution. Exemple:

HTML:

<div ng-init="foo()"> 

JS:

$scope.foo = function() { 
    $timeout(function() { 
     // This code runs after the DOM renders 
    }); 
}); 
Questions connexes