J'ai pris un peu de temps pour déterminer quelle est la meilleure façon de procéder. Je voulais aussi conserver l'état, lorsque l'utilisateur quitte la page puis appuie sur le bouton retour, pour revenir à l'ancienne page; et pas seulement mettre toutes mes données dans le rootscope .
Le résultat final est d'avoir un service pour chaque contrôleur . Dans le contrôleur, vous n'avez que des fonctions et des variables dont vous ne vous souciez pas, si elles sont effacées.
Le service pour le contrôleur est injecté par injection de dépendances. Les services étant des singletons, leurs données ne sont pas détruites comme les données du contrôleur.
Dans le service, j'ai un modèle. le modèle a UNIQUEMENT des données - pas de fonctions -. De cette façon, il peut être converti d'avant en arrière à partir de JSON pour le conserver. J'ai utilisé le localstorage html5 pour la persistance.
Enfin, j'ai utilisé window.onbeforeunload
et $rootScope.$broadcast('saveState');
pour faire savoir à tous les services qu'ils doivent enregistrer leur état et $rootScope.$broadcast('restoreState')
pour leur faire savoir de restaurer leur état (utilisé lorsque l'utilisateur quitte la page et appuie sur le bouton retour pour revenir à la page respectivement).
Exemple de service appelé userService pour mon userController :
app.factory('userService', ['$rootScope', function ($rootScope) {
var service = {
model: {
name: '',
email: ''
},
SaveState: function () {
sessionStorage.userService = angular.toJson(service.model);
},
RestoreState: function () {
service.model = angular.fromJson(sessionStorage.userService);
}
}
$rootScope.$on("savestate", service.SaveState);
$rootScope.$on("restorestate", service.RestoreState);
return service;
}]);
Exemple userController
function userCtrl($scope, userService) {
$scope.user = userService;
}
La vue utilise ensuite une liaison comme celle-ci
<h1>{{user.model.name}}</h1>
Et dans le module d'application , dans la fonction d'exécution, je gère la diffusion de saveState et de restoreState
$rootScope.$on("$routeChangeStart", function (event, next, current) {
if (sessionStorage.restorestate == "true") {
$rootScope.$broadcast('restorestate'); //let everything know we need to restore state
sessionStorage.restorestate = false;
}
});
//let everthing know that we need to save state now.
window.onbeforeunload = function (event) {
$rootScope.$broadcast('savestate');
};
Comme je l'ai mentionné, cela a pris un certain temps pour arriver à ce point. C'est une façon très propre de le faire, mais c'est un peu d'ingénierie de faire quelque chose qui, à mon avis, est un problème très courant lors du développement en Angular.
J'adorerais voir des moyens plus simples, mais aussi propres, de gérer le maintien de l'état sur les contrôleurs, y compris lorsque l'utilisateur quitte et revient à la page.
sessionStorage.restoreState
est défini"true"
. Pour une solution correcte pour conserver les données lors de l'actualisation de la page, regardez ici . Pour des données persistantes lorsque l'itinéraire change, regardez la réponse de carloscarcamo. Tout ce dont vous avez besoin est de mettre les données dans un service.$scope.user = userService;
vous avez quelque chose comme ceci:$scope.name = userService.model.name; $scope.email = userService.model.email;
. Cela fonctionnera-t-il ou changer les variables en vue ne le changerait-il pas dans Service?Un peu en retard pour une réponse mais juste un violon mis à jour avec quelques bonnes pratiques
jsfiddle
la source
updateService
devrait être appelé lorsque le contrôleur est détruit -$scope.$on('$destroy', function() { console.log('Ctrl destroyed'); $scope.updateServiceName($scope.name); });
$ rootScope est une grande variable globale, ce qui convient parfaitement aux choses ponctuelles ou aux petites applications. Utilisez un service si vous souhaitez encapsuler votre modèle et / ou comportement (et éventuellement le réutiliser ailleurs). En plus du groupe Google qui publie l'OP mentionné, voir également https://groups.google.com/d/topic/angular/eegk_lB6kVs/discussion .
la source
Angular ne fournit pas vraiment ce que vous recherchez. Ce que je ferais pour accomplir ce que vous recherchez, c'est d'utiliser les modules complémentaires suivants
Routeur UI et Routeur UI Extras
Ces deux vous fourniront un routage basé sur l'état et des états persistants, vous pouvez passer d'un état à l'autre et toutes les informations seront sauvegardées car la portée "reste vivante" pour ainsi dire.
Consultez la documentation sur les deux car c'est assez simple, les extras du routeur ui ont également une bonne démonstration du fonctionnement des états persistants.
la source
J'ai eu le même problème, c'est ce que j'ai fait: j'ai un SPA avec plusieurs vues dans la même page (sans ajax), voici donc le code du module:
Je n'ai qu'un seul contrôleur pour toutes les vues, mais, le problème est le même que la question, le contrôleur actualise toujours les données, afin d'éviter ce comportement, j'ai fait ce que les gens suggèrent ci-dessus et j'ai créé un service à cette fin, puis le transmettre au contrôleur comme suit:
Maintenant, je peux appeler la fonction de mise à jour à partir de n'importe laquelle de mes vues, transmettre des valeurs et mettre à jour mon modèle, je n'ai pas besoin d'utiliser des apis html5 pour les données de persistance (c'est dans mon cas, peut-être que dans d'autres cas, il serait nécessaire d'utiliser html5 apis comme localstorage et autres).
la source
Une alternative aux services consiste à utiliser le magasin de valeur.
Dans la base de mon application, j'ai ajouté ceci
Et puis dans mon contrôleur, je fais simplement référence au magasin de valeur. Je ne pense pas que cela tienne quelque chose si l'utilisateur ferme le navigateur.
la source
Solution qui fonctionnera pour plusieurs portées et plusieurs variables au sein de ces portées
Ce service était basé sur la réponse d'Anton, mais est plus extensible et fonctionnera sur plusieurs portées et permet la sélection de plusieurs variables de portée dans la même portée. Il utilise le chemin de l'itinéraire pour indexer chaque étendue, puis les noms des variables d'étendue pour indexer un niveau plus profond.
Créez un service avec ce code:
Ajoutez ce code à votre fonction d'exécution dans votre module d'application:
Injectez le service restoreScope dans votre contrôleur (exemple ci-dessous):
L'exemple ci-dessus initialisera $ scope.user à la valeur stockée, sinon sera par défaut la valeur fournie et l'enregistrera. Si la page est fermée, actualisée ou si la route est modifiée, les valeurs actuelles de toutes les variables d'étendue enregistrées seront sauvegardées et seront restaurées la prochaine fois que la route / la page sera visitée.
la source
Vous pouvez utiliser un
$locationChangeStart
événement pour stocker la valeur précédente dans$rootScope
ou dans un service. Lorsque vous revenez, initialisez simplement toutes les valeurs précédemment stockées. Voici une démo rapide utilisant$rootScope
.la source