$ routeProvider détermination propriété permet de retarder le changement d'itinéraire jusqu'à ce que les données sont chargées.
Définissez d'abord une route avec un resolve
attribut comme celui-ci.
angular.module('phonecat', ['phonecatFilters', 'phonecatServices', 'phonecatDirectives']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: PhoneListCtrl,
resolve: PhoneListCtrl.resolve}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: PhoneDetailCtrl,
resolve: PhoneDetailCtrl.resolve}).
otherwise({redirectTo: '/phones'});
}]);
notez que la resolve
propriété est définie sur l'itinéraire.
function PhoneListCtrl($scope, phones) {
$scope.phones = phones;
$scope.orderProp = 'age';
}
PhoneListCtrl.resolve = {
phones: function(Phone, $q) {
// see: https://groups.google.com/forum/?fromgroups=#!topic/angular/DGf7yyD4Oc4
var deferred = $q.defer();
Phone.query(function(successData) {
deferred.resolve(successData);
}, function(errorData) {
deferred.reject(); // you could optionally pass error data here
});
return deferred.promise;
},
delay: function($q, $defer) {
var delay = $q.defer();
$defer(delay.resolve, 1000);
return delay.promise;
}
}
Notez que la définition du contrôleur contient un objet de résolution qui déclare des choses qui devraient être disponibles pour le constructeur du contrôleur. Ici, le phones
est injecté dans le contrôleur et il est défini dans la resolve
propriété.
le resolve.phones
fonction est responsable du retour d'une promesse. Toutes les promesses sont collectées et le changement d'itinéraire est retardé jusqu'à ce que toutes les promesses soient résolues.
Démo de travail: http://mhevery.github.com/angular-phonecat/app/#/phones
Source: https://github.com/mhevery/angular-phonecat/commit/ba33d3ec2d01b70eb5d3d531619bf90153496831
angular.controller()
les définitions de contrôleur de type? Dans le$routeProvider
truc, je pensais que vous deviez utiliser les noms de chaîne des contrôleurs.angular.controller()
, vous pouvez affecter le résultat de cette fonction à une variable (var MyCtrl = angular.controller(...)
), puis travailler avec celle-ci plus loin (MyCtrl.loadData = function(){..}
). Regardez la vidéo d' eggheadVoici un exemple de travail minimal qui fonctionne pour Angular 1.0.2
Modèle:
JavaScript:
http://jsfiddle.net/dTJ9N/3/
Version simplifiée:
Puisque $ http () renvoie déjà une promesse (alias différée), nous n'avons en fait pas besoin de créer la nôtre. Nous pouvons donc simplifier MyCtrl. décidez de:
Le résultat de $ http () contient des données , des statuts , des en- têtes et des objets de configuration , nous devons donc changer le corps de MyCtrl en:
http://jsfiddle.net/dTJ9N/5/
la source
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 demander comment faire cela en utilisant la méthode angular.controller avec une injection de dépendance conviviale pour la minification. Depuis que je viens de travailler, je me suis senti obligé de revenir et d'aider. Voici ma solution (adoptée à partir de la question d'origine et de la réponse de Misko):
Étant donné que ce code est dérivé de la question / réponse la plus populaire, il n'est pas testé, mais il devrait vous envoyer dans la bonne direction si vous comprenez déjà comment rendre le code angulaire convivial pour la minification. La seule partie que mon propre code ne nécessitait pas était une injection de "Phone" dans la fonction de résolution pour les "téléphones", et je n'ai pas du tout utilisé d'objet "delay".
Je recommande également cette vidéo youtube http://www.youtube.com/watch?v=P6KITGRQujQ&list=UUKW92i7iQFuNILqQOUOCrFw&index=4&feature=plcp , ce qui m'a beaucoup aidé
Si cela vous intéresse, j'ai décidé de coller mon propre code (écrit en coffeescript) afin que vous puissiez voir comment je l'ai fait fonctionner.
Pour info, j'utilise à l'avance un contrôleur générique qui m'aide à faire du CRUD sur plusieurs modèles:
la source
resolve
fonction dans le contrôleur, dans les versions récentes d'Angular? Il faut donc le déclarer dans la config comme il est ici?$defer
service non défini , notez que dans la version 1.5.7 d'AngularJS, vous souhaitez utiliser à la$timeout
place.Cette validation , qui fait partie de la version 1.1.5 et supérieure, expose l'
$promise
objet de$resource
. Les versions de ngResource incluant ce commit permettent de résoudre des ressources comme celle-ci:$ routeProvider
manette
la source
GET '/api/1/apps/:appId'
->App.get({id: $routeParams.appId}).$promise();
Je ne peux pas utiliser comme ça$route
selon votre résolution et votre utilisation$route.current.params
. Attention,$routeParams
pointe toujours vers l'ancienne route.Cet extrait est compatible avec l' injection de dépendances (je l'utilise même en combinaison de ngmin et uglify ) et c'est un domaine plus élégant piloté par solution basée sur .
L'exemple ci-dessous enregistre une ressource Phone et un phoneRoutes constant , qui contient toutes vos informations de routage pour ce domaine (téléphone). Quelque chose que je n'ai pas aimé dans la réponse fournie était l'emplacement de la logique de résolution - le module principal ne devrait rien savoir ou être dérangé par la façon dont les arguments de ressource 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 ne l'êtes pas: vous devriez) vous n'avez qu'à écrire les fonctions de résolution avec la convention du tableau DI.
La pièce suivante injecte les données de routage lorsque le module est dans l'état de configuration et les applique au $ routeProvider .
Tester la configuration de l'itinéraire avec cette configuration est également assez simple:
Vous pouvez le voir en pleine gloire dans ma dernière expérience (à venir) . Bien que cette méthode fonctionne bien pour moi, je me demande vraiment pourquoi l'injecteur $ ne retarde pas la construction de quoi que ce soit lorsqu'il détecte l'injection de tout ce qui est un objet promis ; cela rendrait les choses tellement plus faciles.
Edit: utilisé Angular v1.2 (rc2)
la source
I really wonder why the $injector isn't delaying construction of anything when it detects injection of anything that is a promise object
Je suppose qu'ils ont omis cette fonctionnalité car cela pourrait encourager les modèles de conception qui affectent négativement la réactivité des applications. L'application idéale dans leur esprit est une application vraiment asynchrone, donc la résolution devrait être un cas de pointe.Retarder l'affichage de l'itinéraire entraînera certainement un enchevêtrement asynchrone ... pourquoi ne pas simplement suivre l'état de chargement de votre entité principale et l'utiliser dans la vue. Par exemple, dans votre contrôleur, vous pouvez utiliser à la fois les rappels de réussite et d'erreur sur ngResource:
Ensuite, dans la vue, vous pouvez faire n'importe quoi:
la source
J'ai travaillé à partir du code de Misko ci-dessus et c'est ce que j'ai fait avec. Il s'agit d'une solution plus récente car elle
$defer
a été remplacée par$timeout
.$timeout
Cependant, la substitution attendra le délai d'expiration (dans le code de Misko, 1 seconde), puis retournera les données en espérant qu'elles soient résolues à temps. De cette façon, il revient dès que possible.la source
Utilisation d'AngularJS 1.1.5
Mise à jour de la fonction «téléphones» dans la réponse de Justen en utilisant AngularJS 1.1.5 syntaxe .
Original:
Actualisé:
Beaucoup plus court grâce à l'équipe Angular et aux contributeurs. :)
C'est aussi la réponse de Maximilian Hoffmann. Apparemment, cet engagement est devenu 1.1.5.
la source
$promise
dans les documents . Il pourrait avoir été supprimé à partir de la v2.0 +.Vous pouvez utiliser la propriété de résolution $ routeProvider pour retarder le changement d'itinéraire jusqu'à ce que les données soient chargées.
Notez que le
resolve
propriété est définie sur l'itinéraire.EntitiesCtrlResolve
etEntityCtrlResolve
est constante objets définis dans même fichierEntitiesCtrl
et lesEntityCtrl
contrôleurs.la source
J'aime l'idée de darkporter, car il sera facile pour une équipe de développeurs novice d'AngularJS de comprendre et de travailler immédiatement.
J'ai créé cette adaptation qui utilise 2 divs, une pour la barre de chargement et une autre pour le contenu réel affiché après le chargement des données. La gestion des erreurs se ferait ailleurs.
Ajoutez un indicateur «prêt» à $ scope:
En vue html:
Voir aussi: Boostrap progress bar docs
la source
J'ai aimé les réponses ci-dessus et j'ai beaucoup appris d'eux, mais il y a quelque chose qui manque dans la plupart des réponses ci-dessus.
J'étais coincé dans un scénario similaire où je résolvais l'url avec des données récupérées dans la première demande du serveur. Le problème que j'ai rencontré était de savoir si la promesse était
rejected
.Je travaillais avec un fournisseur personnalisé qui permet de revenir un
Promise
qui a été résolu par laresolve
de$routeProvider
au moment de la phase de configuration.Ce que je veux souligner ici, c'est le concept de
when
fait quelque chose comme ça.Il voit l'url dans la barre d'url puis le
when
bloc correspondant dans le contrôleur appelé et la vue est référencée jusqu'à présent tout va bien.Disons que j'ai le code de phase de configuration suivant.
Sur l'URL racine du navigateur, le premier bloc d'exécution est appelé, sinon il
otherwise
est appelé.Imaginons qu'un scénario que j'ai frappé rootUrl dans la
AuthServicePrivider.auth()
fonction de barre d'adresse soit appelé.Disons que la promesse retournée est en état de rejet quoi alors ???
Rien n'est rendu du tout.
Otherwise
Le bloc ne sera pas exécuté comme pour toute URL non définie dans le bloc de configuration et inconnue de la phase de configuration angularJs.Nous devrons gérer l'événement qui est renvoyé lorsque cette promesse n'est pas tenue. En cas d'échec se
$routeChangeErorr
fait tirer dessus$rootScope
.Il peut être capturé comme indiqué dans le code ci-dessous.
IMO C'est généralement une bonne idée de mettre le code de suivi des événements dans le bloc d'exécution de l'application. Ce code s'exécute juste après la phase de configuration de l'application.
De cette façon, nous pouvons gérer l'échec de la promesse au moment de la phase de configuration.
la source
J'ai eu une interface de panneau coulissant multi-niveaux complexe, avec une couche d'écran désactivée. Création d'une directive sur la désactivation de la couche d'écran qui créerait un événement de clic pour exécuter l'état comme
produisaient un effet de scintillement. history.back () au lieu de cela a bien fonctionné, mais ce n'est pas toujours de retour dans l'histoire dans mon cas. Donc, ce que je découvre, c'est que si je crée simplement l'attribut href sur mon écran de désactivation au lieu de state.go, cela fonctionne comme un charme.
Directive «retour»
app.js Je viens de sauvegarder l'état précédent
la source
Une solution possible pourrait être d'utiliser la directive ng-cloak avec l'élément où nous utilisons les modèles, par exemple
Je pense que celui-ci prend le moins d'effort.
la source