AngularJS: Comment faire pour exécuter un code supplémentaire une fois AngularJS a rendu un modèle?
J'ai Angulaire du modèle dans les DOM. Lors de mon contrôleur reçoit de nouvelles données à partir d'un service, il met à jour le modèle dans le $scope, et re-rend le modèle. Tout bon jusqu'ici.
Le problème est que je dois aussi faire un travail supplémentaire après le modèle a été re-rendus et dans les DOM (dans ce cas, un plugin jQuery).
Il semble qu'il devrait y avoir un événement à écouter, comme AfterRender, mais je ne trouve pas une telle chose. Peut-être une directive serait une façon de faire, mais il semblait à feu trop tôt aussi.
Ici est un jsFiddle décrivant mon problème: Violon-AngularIssue
== Mise à JOUR ==
Basée sur des observations utiles, je l'ai donc passé à une directive de la poignée de manipulation du DOM, et mis en œuvre un modèle de $regarder à l'intérieur de la directive. Cependant, je suis encore en ayant le même problème; le code à l'intérieur de $regarder événement se déclenche avant que le modèle a été compilé et inséré dans les DOM, par conséquent, le plugin jquery est toujours de l'évaluation d'une table vide.
Fait intéressant, si je supprime l'appel asynchrone le tout fonctionne très bien, donc c'est un pas dans la bonne direction.
Voici ma mise à jour de Violon pour tenir compte de ces changements: http://jsfiddle.net/uNREn/12/
- Cela semble similaire à une question que j'avais. stackoverflow.com/questions/11444494/.... Peut-être quelque chose là-bas peut vous aider.
Vous devez vous connecter pour publier un commentaire.
Ce post est vieux, mais j'ai changer votre code:
voir jsfiddle.
J'espère que cela vous aide à
Tout d'abord, le lieu à ne plaisante pas avec le rendu des directives. Mon conseil serait pour envelopper DOM la manipulation de plugins jQuery par les directives comme celle-ci.
J'ai eu le même problème et est venu avec cet extrait. Il utilise
$watch
et$evalAsync
pour assurer que votre code s'exécute après les directives telles queng-repeat
ont été résolus et de modèles tels que{{ value }}
suis rendu.Espère que cela peut vous aider à éviter quelques difficultés.
link
fonction avec untemplateUrl
.Suivantes Misko du conseil, si vous voulez opération asynchrone, alors au lieu de $timeout() (qui ne fonctionne pas)
utiliser $evalAsync() (qui fonctionne)
Violon. J'ai aussi ajouté un "supprimer la ligne de données" lien qui vous permettra de modifier $champ d'application.les affectations, la simulation d'un changement de données/modèle-pour indiquer que la modification de données fonctionne.
La Runtime section de la vue d'ensemble Conceptuelle page explique que evalAsync devrait être utilisé lorsque vous avez besoin de quelque chose pour se produire à l'extérieur de la trame de pile, mais avant le rend navigateur. (Deviner ici... "current frame de pile" comprend probablement Angulaire DOM mises à jour.) Utiliser $timeout si vous besoin de quelque chose de se produire après la rend navigateur.
Cependant, comme vous l'avez déjà trouvé, je ne pense pas qu'il existe un besoin pour une opération asynchrone ici.
$scope.$evalAsync($scope.assignmentsLoaded(data));
ne ferait aucun sens de l'OMI. L'argument en faveur de$evalAsync()
devrait être une fonction. Dans votre exemple, vous êtes à l'appel de la fonction à la fois une fonction doit être enregistré pour exécution ultérieure.J'ai trouvé le plus simple (bon marché et gai de) la solution est tout simplement d'ajouter un vide span avec ng-show = "someFunctionThatAlwaysReturnsZeroornothing()" à la fin du dernier élément de rendu. Cette fonction sera exécutée lorsque pour vérifier si la durée de l'élément doit être affiché. Exécuter tout autre code dans cette fonction.
Je me rends compte que ce n'est pas la façon la plus élégante de faire les choses, cependant, il fonctionne pour moi...
J'ai eu une situation similaire, bien que légèrement inversée où j'avais besoin de supprimer un indicateur de chargement lorsqu'une animation a commencé, sur les appareils mobiles angulaire de l'initialisation a été beaucoup plus rapide que l'animation soit affiché, et à l'aide d'un ng-manteau était insuffisante de l'indicateur de chargement a été retiré bien avant tout réel des données a été affichée. Dans ce cas, j'ai juste ajouté mon retour 0 fonction du premier élément affiché, et dans cette fonction renversé le var qui masque l'indicateur de chargement. (bien sûr, j'ai ajouté un ng-hide de l'indicateur de chargement déclenchée par cette fonction.
$anchorScroll
service être appelée après la DOM rendus et rien ne semblait faire l'affaire mais ce. Hackish mais fonctionne.Je pense que vous êtes à la recherche pour $evalAsync http://docs.angularjs.org/api/ng.$rootScope.Champ#$evalAsync
J'ai enfin trouvé la solution, j'ai utilisé un RESTE de mise à jour de ma collection. Afin de convertir datatable jquery est la suite du code:
j'ai dû le faire assez souvent. j'ai une directive et le besoin de faire quelques jquery trucs après le modèle des choses est entièrement chargé dans les DOM. j'ai donc mis ma logique dans le lien: fonctionnement de la directive et de placer le code dans un setTimeout(function() { ..... }, 1); le setTimout se déclenche après le DOM est chargé et 1 milisecond est le plus court laps de temps après le DOM est chargé d'avant le code à l'exécution. cela semble fonctionner pour moi mais je ne souhaite angulaire soulevé un événement une fois qu'un modèle a été fait de chargement, de sorte que les directives utilisées par ce modèle pourrait faire jquery choses et d'accéder à des éléments du DOM. espérons que cette aide.
Vous pouvez également créer une directive qui exécute votre code dans la fonction de lien.
Voir que stackoverflow répondre.
Ni $scope.$evalAsync() ou $timeout(fn, 0) a travaillé de manière fiable pour moi.
J'ai eu de combiner les deux. J'ai fait une directive et aussi mettre une priorité plus élevée que la valeur par défaut pour faire bonne mesure. Voici une directive pour elle (Remarque j'utilise ngInject d'injecter des dépendances):
À l'appel de la directive, vous voulez faire cela:
Si vous voulez l'appeler, après une ng-repeat est fait en cours, j'ai ajouté un vide durée de mon ng-repeat et ng-si="$last":
Je suis venu avec une jolie solution simple. Je ne suis pas sûr de savoir si c'est la bonne façon de le faire, mais il fonctionne dans un sens pratique. Nous allons regarder directement ce que nous voulons être rendus. Par exemple, dans une directive qui comprend certains
ng-repeat
s, je regardais pour la longueur du texte (vous pouvez avoir d'autres choses!) de paragraphes ou de l'ensemble de l'html. La directive sera comme ceci:NOTE que le code s'exécute après rendu changements assez complet de rendu. Mais je suppose que dans la plupart des cas, vous pouvez gérer les situations au moment de rendu des changements se produisent. Aussi, vous pourriez penser à la comparaison de ce
p
longueur s (ou toute autre mesure) avec votre modèle si vous voulez exécuter votre code une fois après le rendu terminé. J'apprécie toutes les pensées et/ou commentaires sur ce.Vous pouvez utiliser la fonction jQuery Relais module de la angular-ui utils. J'ai réussi à lier un jQuery touch carrousel plugin pour certaines images que j'ai récupérer asynchrone à partir d'un service web et de les rendre avec ng-repeat.
Dans certains scénarios où vous mettez à jour un service et de les rediriger vers un nouveau point de vue(page) et ensuite votre directive est chargé avant vos services sont mis à jour, alors vous pouvez utiliser $rootScope.$diffusion si votre $regarder ou $timeout échoue
Vue
Contrôleur
Directive