Retarder AngularJS changement d'itinéraire jusqu'modèle chargé d'empêcher le scintillement
Je me demandais si il existe un moyen (similaire à Gmail) pour AngularJS pour retard montrant une nouvelle route jusqu'à ce que après chaque modèle et ses données ont été extraites à l'aide de ses services respectifs.
Par exemple, si il y avait un ProjectsController
la liste de tous les Projets et project_index.html
qui a été le modèle qui a montré ces Projets, Project.query()
serait récupéré complètement avant d'afficher la nouvelle page.
Jusqu'alors, l'ancienne page continuera à afficher (par exemple, si j'ai été la navigation sur une autre page, puis a décidé de voir ce Projet index).
Vous devez vous connecter pour publier un commentaire.
$routeProvider résoudre propriété permet de retarder la route à modifier jusqu'à ce que les données sont chargées.
D'abord définir un itinéraire avec
resolve
attribut de ce genre.avis que le
resolve
propriété est définie sur la route.Avis que le contrôleur de définition contient une détermination de l'objet qui déclare des choses qui devraient être à la disposition du contrôleur de constructeur. Ici le
phones
est injecté dans le contrôleur et il est défini dans laresolve
propriété.La
resolve.phones
fonction est responsable du retour d'une promesse. Toutes les promesses sont recueillies et le changement d'itinéraire est retardée jusqu'à ce que toutes les promesses sont résolus.De travail de démonstration: http://mhevery.github.com/angular-phonecat/app/#/phones
Source: https://github.com/mhevery/angular-phonecat/commit/ba33d3ec2d01b70eb5d3d531619bf90153496831
angular.controller()
type de contrôleur de définitions? Dans le$routeProvider
trucs, j'ai pensé que vous deviez utiliser des noms de chaîne de contrôleurs.angular.controller()
, vous pouvez affecter le résultat de cette fonction à une variable (var MyCtrl = angular.controller(...)
), et ensuite travailler avec d'autres (MyCtrl.loadData = function(){..}
). Découvrez intellectuel de la vidéo, le code est affiché là tout de suite: tête d'oeuf.io/vidéo/0uvAseNXDr0a = angular.module('a', []); a.controller(function () {}) == a.controller(function (){})
afin de ne pas travailler avec plusieurs contrôleurs.$routeChangeError
Voici un travail minimale exemple qui fonctionne Angulaire 1.0.2
Modèle:
JavaScript:
http://jsfiddle.net/dTJ9N/3/
Version simplifiée:
Depuis $http() retourne déjà une promesse (aka différé), nous n'avez pas besoin de créer notre propre. Nous pouvons simplifier MyCtrl. résoudre à:
Le résultat de $http() contient données, statut, les en-têtes de et config objets, nous avons donc besoin de modifier le corps de MyCtrl à:
http://jsfiddle.net/dTJ9N/5/
Unknown provider: datasetsProvider <- datasets
function($http) { return $http({method: 'GET', url: '/someUrl'}) .then( function(data){ return data;}, function(reason){return 'error value';} ); }
Je vois certaines personnes demandant comment faire cela à l'aide de l'angle.la méthode du contrôleur avec minification respectueux de l'injection de dépendances. Depuis que je viens de recevoir ce travail je me suis senti obligé de revenir et de les aider. Voici ma solution (adopté à partir de la question d'origine et de Misko réponse):
Puisque ce code est dérivé de la question/réponse c'est non testé, mais il doit vous envoyer dans la bonne direction si vous comprenez déjà comment faire de minification amical angulaire de code. La seule partie que mon propre code ne nécessite pas été une injection de "Téléphone" dans la détermination de la fonction de 'phones', ni ai-je utiliser un "report" de l'objet à tous.
Je recommande également cette vidéo sur youtube http://www.youtube.com/watch?v=P6KITGRQujQ&list=UUKW92i7iQFuNILqQOUOCrFw&index=4&feature=plcp , qui m'a aidé un peu
Devrait vous intéresser, j'ai décidé de coller mon propre code (Écrit en coffeescript) de sorte que vous pouvez voir comment j'ai eu de travail.
Pour info, à l'avance-je utiliser un contrôleur générique qui m'aide à faire du CRUD sur plusieurs modèles:
resolve
fonction dans le contrôleur, dans les versions récentes de Angulaire? Donc, il doit être déclaré à droite dans la config que c'est ici?$defer
service, ne remarque que dans la version 1.5.7 d'AngularJS, vous souhaitez utiliser$timeout
à la place.Ce commit, qui fait partie de la version 1.1.5 et au-dessus, expose le
$promise
objet de$resource
. Les Versions de ngResource y compris ce commit permettre la résolution des ressources comme ceci:$routeProvider
contrôleur
GET '/api/1/apps/:appId'
-->App.get({id: $routeParams.appId}).$promise();
je ne peux pas l'utiliser comme ceci$route
à votre détermination et à l'utilisation$route.current.params
. Attention,$routeParams
pointe toujours vers l'ancienne route.Cet extrait est l'injection de dépendance sympathique (j'ai même l'utiliser en combinaison de ngmin et uglify) et c'est un plus élégant domain driven base de solution.
L'exemple ci-dessous enregistre un Téléphone ressources et un constante phoneRoutes, qui contient toutes vos informations de routage pour que (de téléphone) de domaine. Quelque chose que je n'aimais pas dans la réponse était l'emplacement de la résoudre logique-la principal module ne devrait pas savoir quoi que ce soit ou être dérangé au sujet de la façon dont la ressource arguments sont fournis au contrôleur. De cette façon, la logique reste dans le même domaine.
Remarque: si vous utilisez ngmin (et si vous n'êtes pas: vous devez vous n'avez qu'à écrire le résoudre fonctions avec la DI tableau convention.
Le morceau suivant est d'injecter de l'acheminement des données lorsque le module est dans la configuration de l'état et de l'appliquer à la $routeProvider.
Test de la route de configuration avec ce programme d'installation est également assez facile:
Vous pouvez le voir dans toute sa gloire dans mon dernier (à venir) expérience.
Bien que cette méthode fonctionne très bien pour moi, je me demande vraiment pourquoi le $injecteur n'est pas de retarder la construction de rien lorsqu'il détecte l'injection de rien qui est un promesse objet; il rendrait les choses soooOOOOOooOOOOO beaucoup plus facile.
Edit: utilisé Angulaire v1.2(rc2)
I really wonder why the $injector isn't delaying construction of anything when it detects injection of anything that is a promise object
Je devine qu'ils omis cette fonctionnalité, car il pourrait encourage les modèles de conception que l'effet négatif de la réactivité des applications. L'idéal application dans leur esprit en est une qui est vraiment asynchrone, afin que la résolution doit être un cas limite.Retarder montrant l'itinéraire est sûr de conduire à une asynchrones enchevêtrement... pourquoi ne pas simplement suivre l'état de chargement de votre entité principale et de l'utiliser dans la vue. Par exemple, dans votre contrôleur, vous pouvez utiliser à la fois le succès et l'erreur de rappels sur ngResource:
Puis dans la vue, vous pourriez faire n'importe quoi:
J'ai travaillé à partir de Misko du code ci-dessus et c'est ce que j'ai fait avec elle. C'est une solution en cours depuis
$defer
a été modifié pour$timeout
. La substitution$timeout
cependant attendre le délai d'attente (en Misko code, à 1 seconde), puis renvoyer les données en espérant que c'est résolu dans le temps. Avec cette façon, il retourne le plus vite possible.Utilisant AngularJS 1.1.5
Mise à jour du téléphone de fonction dans Justen de la réponse à l'aide de AngularJS 1.1.5 syntaxe.
Original:
Mise à jour:
Beaucoup plus court grâce à l'angle de l'équipe et les collaborateurs. 🙂
C'est aussi la réponse de Maximilien Hoffmann. Apparemment qui s'engagent dans 1.1.5.
$promise
dans la doc. Il pourrait avoir été prise à titre de v2.0+.Vous pouvez utiliser $routeProvider résoudre propriété de retarder la route à modifier jusqu'à ce que les données sont chargées.
Avis que le
resolve
propriété est définie sur la route.EntitiesCtrlResolve
etEntityCtrlResolve
est constant les objets définis dans le même fichier queEntitiesCtrl
etEntityCtrl
contrôleurs.J'aime darkporter de l'idée, car il sera facile pour l'équipe de développement de nouvelles à AngularJS pour comprendre et travaillé tout de suite.
J'ai créé cette adaptation qui utilise les 2 divs, un pour le chargeur de barre et un autre pour le contenu affiché après le chargement des données. Gestion des erreurs serait fait ailleurs.
Ajouter un "prêt" drapeau de $portée:
En mode html:
Voir aussi: Bootstrap barre de progression docs
J'ai aimé les réponses ci-dessus, et beaucoup appris d'eux, mais il y a quelque chose qui manque dans la plupart des réponses ci-dessus.
J'ai été coincé dans un scénario similaire, où j'ai été la résolution des url avec certaines données qui sont extraites dans le premier demande à partir du serveur. Problème que j'ai été confrontés était que si la promesse est
rejected
.J'ai été en utilisant un fournisseur personnalisé qui permet de retourner une
Promise
qui a été résolu par laresolve
de$routeProvider
au moment de l'étape de configuration.Ce que je veux souligner ici, c'est le concept de
when
il fait quelque chose comme ça.Il voit l'url dans la barre d'adresse url et puis respectifs
when
bloc appelé contrôleur et la vue est appelé so far so good.Permet de dire que j'ai la configuration suivante de la phase de code.
Sur la racine de l'url dans le navigateur premier bloc de la course appelée autrement
otherwise
est appelée.Imaginons un scénario que j'ai frappé rootUrl dans la barre d'adresse
AuthServicePrivider.auth()
fonction est appelée.Permet de dire que la Promesse est retourné dans rejeter état alors, quoi???
Rien ne sera rendu à tous.
Otherwise
bloc ne sera exécutée comme pour toutes les url qui n'est pas défini dans le fichier de configuration de bloc et est inconnu à angularJs étape de configuration.Nous aurons à gérer l'événement qui obtient déclenché lorsque cette promesse n'est pas résolu. En cas d'échec
$routeChangeErorr
obtient le feu sur$rootScope
.Il peut être capturé comme indiqué dans le code ci-dessous.
De l'OMI, Il est généralement une bonne idée de mettre le code de suivi des événements dans l'exécution du bloc d'application. Ce code exécuté juste après l'étape de configuration de l'application.
De cette façon, nous pouvons nous occuper de la promesse de l'échec au moment de l'étape de configuration.
J'ai eu un complexe multi-niveau coulissantes panneau d'interface, désactivé l'écran de la couche. La création de la directive sur désactiver l'écran de la couche de créer l'événement click pour exécuter l'état comme
ont été la production d'une pichenette de l'effet. l'histoire.back() au lieu de il a travaillé ok, cependant ce n'est pas toujours en arrière dans l'histoire, dans mon cas. DONC ce que j'ai trouver c'est que si il suffit de créer de l'attribut href, sur mon désactiver l'écran à la place de l'etat.aller , a travaillé comme un charme.
La Directive "retour"
app.js je viens de sauver de l'état antérieur
Une solution possible pourrait être d'utiliser le ng-manteau de la directive avec l'élément où nous utilisons les modèles par exemple
Je pense que celui-ci prend moins d'efforts.