web-dev-qa-db-fra.com

Exécuter Javascript APRÈS Angular A terminé le chargement de toutes les vues

Je crée une application Web à l'aide d'Angular et j'essaie de trouver un moyen d'attendre que tous les data-ng-include les éléments ont été évalués et incluent le chargement terminé. Par exemple, le menu est une vue qui est chargée, tout comme le contenu principal de chaque page, donc au moins il y a deux data-ng-includes qui sont évalués et chargés. De plus, le menu include a imbriqué data-ng-repeats qui construisent mon menu. J'ai besoin d'un moyen pour lancer le script APRÈS toutes ces inclusions et toutes les fonctions angular à l'intérieur ont été chargées et le DOM est réellement prêt.

Y a-t-il un événement qui se déclenche lorsque Angular a terminé la configuration de la page?

L'implémentation d'AnguarJS est basique et nous l'utilisons essentiellement pour les modèles via l'utilisation de data-ng-include. Chaque page est une vue (pas une vue angular, juste un fichier html), chargée via data-ng-include, avec l'en-tête et le pied de page au-dessus et en dessous. L'en-tête charge également dynamiquement un vue globale (encore une fois pas un fichier html angular vue) qui comprend angulaire.

Jusqu'à présent, le menu est la seule chose qui utilise AngularJS pour autre chose que des modèles. Il l'utilise pour créer un menu à l'aide d'un objet JSON généré dynamiquement par JSP et inséré dans le DOM renvoyé par le serveur.

Afin de faciliter la vie des utilisateurs, toute sorte de fonctionnalité JavaScript répétée est codée en modules, qui sont détectés au chargement de la page et chargés dynamiquement à l'aide d'un attribut data-features sur l'élément auquel la fonctionnalité JavaScript doit être attachée à.

Par exemple, vous pouvez avoir <div id="mySubMenu" data-features="subMenu"></div>. Au chargement de la page, chaque élément avec un élément data-features est détecté et le module JS associé chargé, dans ce cas, nous chargerions /scripts/modules/subMenu.js.

Ce dont j'ai besoin, c'est d'un moyen de retarder l'exécution de cette détection et de cette pièce jointe jusqu'à ce que tous les éléments résultant d'une fonction include ou autre angular soit sur la page et prêt à être manipulé, d'autant plus qu'il peut y avoir être des éléments avec des attributs de données dans ces inclusions.

Quelqu'un ailleurs avait mentionné mettre un contrôleur sur le corps et ne rien y mettre mais:

$scope.$on('$viewContentLoaded', function() {
    // Init Features Here
});

Cela n'a pas fonctionné, donc je suis ici à la recherche d'autres options.

J'ai fini par aller avec la solution de Theo dans cette question: Envoi d'événement lorsque angular.js a fini de charger

29
StephenRios

Je pense que la réponse appropriée est NON. Vous devez changer la façon dont vous regardez votre application et votre modèle et l'adapter à la "manière angulaire". Il existe très probablement un moyen plus sain de réaliser ce dont vous avez besoin. Si vous devez attacher des événements à des éléments, vous voudrez probablement utiliser une directive, mais bien sûr, je n'ai pas suffisamment d'informations pour juger à ce stade de ce qui est le mieux.

angular.module avec directives est une bonne option à explorer.

Voici une démonstration de plunker sur la façon d'utiliser les deux avec un plug-in JQUERY:

http://plnkr.co/edit/WGdNEM?p=preview

Voici un exemple avec une directive sur un fichier séparé:

http://plnkr.co/edit/YNBSWPLeWqsfGvOTwsMB?p=preview

3
Dalorzo

sur le contenu chargé:

$rootScope.$on('$includeContentLoaded', function() {
    //do your will
});

sur le contenu demandé:

$rootScope.$on('$includeContentRequested', function() {
    //...
});
15
easyrider

Je suis certain que ce n'est pas la bonne façon de procéder, mais ...

Mettre la fonction ci-dessous dans mon contrôleur de vue, a exécuté la fonction après que la vue se soit chargée dans mon application. Je crois que la fonction est exécutée dans le prochain cycle de résumé suivant le chargement de la vue (corrigez-moi ici en cas d'erreur), elle est donc exécutée une fois la page formée.

setTimeout(function(){
  //do this after view has loaded :)
  console.log('success!');
}, 0);

Il est possible que vous puissiez les chaîner via des rappels et/ou utiliser une bibliothèque parallèle asynchrone pour exécuter une autre fonction, après le retour de chacune des vues setTimeouts.

6
David Anderton

Vous pouvez utiliser une promesse JQuery et remplir cette promesse dans votre contrôleur racine angular. Configurez la promesse avant l'exécution du code angular contrôleur ou jquery:

var AppReadyDeferred = $.Deferred();
var AppReadyPromise = AppReadyDeferred.promise();

Dans votre angular une fois que tout est prêt, faites

AppReadyDeferred.resolve();

Et dans votre code jQuery attendez qu'il soit résolu

window.AppReadyPromise.done(() => {
  // Angular is ready to go!;
});
2
GeekyMonkey

Utilisez ng-cloak pour retarder l'affichage des modèles avant la compilation. Vous pouvez également ajouter un champ caché en tant que tout dernier enfant à votre élément html qui a ng-cloak (mieux vaut l'utiliser dans la balise body ou là où votre ng-app démarre), puis vous pouvez vérifier l'existence de cet élément caché dans un boucle d'intervalle

Votre partie de champ caché serait comme ça

<div ng-include="'ngtplhidden'"></hidden>
<script type="text/ng-template" id="ngtplhidden">
<span id="elemidToCheckInAnIntervalFunc"></span>
</script>
1
Nihat