Demorei um pouco para descobrir qual é a melhor maneira de fazer isso. Eu também queria manter o estado, quando o usuário sai da página e pressiona o botão Voltar, para voltar à página antiga; e não apenas colocar todos os meus dados no rootscope .
O resultado final é ter um serviço para cada controlador . No controlador, você apenas possui funções e variáveis com as quais não se importa, se elas estiverem limpas.
O serviço para o controlador é injetado por injeção de dependência. Como os serviços são singletons, seus dados não são destruídos como os dados no controlador.
No serviço, eu tenho um modelo. o modelo SOMENTE possui dados - sem funções -. Dessa forma, ele pode ser convertido para frente e para trás do JSON para persistir. Eu usei o armazenamento local html5 para persistência.
Por fim, usei window.onbeforeunload
e $rootScope.$broadcast('saveState');
avisei a todos os serviços que eles devem salvar seu estado e $rootScope.$broadcast('restoreState')
avise-os para restaurar seu estado (usado para quando o usuário sai da página e pressiona o botão Voltar para retornar à página, respectivamente).
Exemplo de serviço chamado userService para meu 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;
}]);
exemplo userController
function userCtrl($scope, userService) {
$scope.user = userService;
}
A visualização então usa ligação como esta
<h1>{{user.model.name}}</h1>
E no módulo do aplicativo , dentro da função de execução, eu lida com a transmissão do saveState e 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');
};
Como mencionei, demorou um pouco para chegar a esse ponto. É uma maneira muito limpa de fazer isso, mas é um pouco de engenharia fazer algo que eu suspeitaria ser um problema muito comum no desenvolvimento em Angular.
Eu adoraria ver mais fácil, mas como maneiras limpas de lidar com a manutenção do estado entre controladores, inclusive quando o usuário sai e retorna à página.
sessionStorage.restoreState
está definido"true"
. Para que uma solução correta persista os dados quando a página for atualizada, consulte aqui . Para dados persistentes quando a rota muda, veja a resposta de carloscarcamo. Tudo que você precisa é colocar os dados em um serviço.$scope.user = userService;
você tem algo parecido com isto:$scope.name = userService.model.name; $scope.email = userService.model.email;
. Funcionará ou alterar as variáveis em vista não o alterará no Serviço?Um pouco atrasado para uma resposta, mas apenas atualizou o violino com algumas práticas recomendadas
jsfiddle
fonte
updateService
deve ser chamada quando o controlador for destruído$scope.$on('$destroy', function() { console.log('Ctrl destroyed'); $scope.updateServiceName($scope.name); });
$ rootScope é uma grande variável global, adequada para coisas pontuais ou aplicativos pequenos. Use um serviço se desejar encapsular seu modelo e / ou comportamento (e possivelmente reutilizá-lo em outro lugar). Além da postagem do grupo do Google no OP mencionado, consulte também https://groups.google.com/d/topic/angular/eegk_lB6kVs/discussion .
fonte
Angular realmente não fornece o que você está procurando imediatamente. O que eu faria para realizar o que você procura é usar os seguintes complementos
UI Router e UI Router Extras
Esses dois fornecerão roteamento baseado em estado e estados de aderência. Você pode alternar entre estados e todas as informações serão salvas, pois o escopo "permanece ativo", por assim dizer.
Verifique a documentação dos dois, já que é bastante simples, os extras do ui router também apresentam uma boa demonstração de como os estados de aderência funcionam.
fonte
Eu tive o mesmo problema, foi o que fiz: Eu tenho um SPA com várias visualizações na mesma página (sem ajax), portanto, este é o código do módulo:
Eu tenho apenas um controlador para todas as visualizações, mas, o problema é o mesmo da pergunta, o controlador sempre atualiza os dados. Para evitar esse comportamento, fiz o que as pessoas sugerem acima e criei um serviço para esse fim, depois passe-o para o controlador da seguinte maneira:
Agora eu posso chamar a função de atualização de qualquer uma das minhas visualizações, passar valores e atualizar meu modelo. Não preciso usar apis html5 para dados de persistência (no meu caso, talvez em outros casos seja necessário usar html5 APIs como armazenamento local e outras coisas).
fonte
Uma alternativa aos serviços é usar o armazenamento de valor.
Na base do meu aplicativo, adicionei este
E então, no meu controlador, apenas refiro o armazenamento de valor. Eu não acho que vale tudo se o usuário fechar o navegador.
fonte
Solução que funcionará para vários escopos e várias variáveis dentro desses escopos
Esse serviço foi baseado na resposta de Anton, mas é mais extensível e funcionará em vários escopos e permite a seleção de várias variáveis de escopo no mesmo escopo. Ele usa o caminho da rota para indexar cada escopo e, em seguida, os nomes de variáveis do escopo para indexar um nível mais a fundo.
Crie um serviço com este código:
Adicione este código à sua função de execução no seu módulo de aplicativo:
Injete o serviço restoreScope no seu controlador (exemplo abaixo):
O exemplo acima inicializará $ scope.user com o valor armazenado, caso contrário, será padronizado com o valor fornecido e o salvará. Se a página for fechada, atualizada ou a rota for alterada, os valores atuais de todas as variáveis de escopo registradas serão salvos e restaurados na próxima vez que a rota / página for visitada.
fonte
Você pode usar
$locationChangeStart
event para armazenar o valor anterior em$rootScope
ou em um serviço. Quando você voltar, basta inicializar todos os valores armazenados anteriormente. Aqui está uma demonstração rápida usando$rootScope
.fonte