Poświęciłem trochę czasu, aby znaleźć najlepszy sposób na zrobienie tego. Chciałem też zachować stan, w którym użytkownik opuszcza stronę, a następnie naciska przycisk Wstecz, aby wrócić do starej strony; a nie tylko umieszczać wszystkie moje dane w głównym zakresie .
Końcowym rezultatem jest usługa dla każdego kontrolera . W kontrolerze masz tylko funkcje i zmienne, o które nie dbasz, jeśli są wyczyszczone.
Usługa dla kontrolera jest wstrzykiwana przez iniekcję zależności. Ponieważ usługi są singletonami, ich dane nie są niszczone tak jak dane w kontrolerze.
W serwisie mam modelkę. model zawiera TYLKO dane - bez funkcji -. W ten sposób można go konwertować z formatu JSON do przodu i do tyłu, aby go zachować. Użyłem lokalnego magazynu html5 dla trwałości.
Na koniec użyłem window.onbeforeunload
i $rootScope.$broadcast('saveState');
powiadomiłem wszystkie usługi, że powinny zapisać swój stan, i $rootScope.$broadcast('restoreState')
aby dać im znać, aby przywrócić ich stan (używane, gdy użytkownik opuszcza stronę i naciska przycisk Wstecz, aby odpowiednio wrócić do strony).
Przykładowa usługa o nazwie userService dla mojego 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;
}]);
Przykład userController
function userCtrl($scope, userService) {
$scope.user = userService;
}
Widok następnie używa takiego wiązania
<h1>{{user.model.name}}</h1>
Natomiast w module aplikacji , w ramach funkcji run, obsługuję rozgłaszanie stanów saveState i 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');
};
Jak wspomniałem, dojście do tego punktu zajęło trochę czasu. Jest to bardzo czysty sposób, ale zrobienie czegoś, co podejrzewam, że jest bardzo częstym problemem podczas programowania w Angular, wymaga sporo inżynierii.
Chciałbym widzieć łatwiejsze, ale jako przejrzyste sposoby radzenia sobie z utrzymywaniem stanu między kontrolerami, w tym gdy użytkownik opuszcza stronę i wraca do niej.
sessionStorage.restoreState
jest ustawione"true"
. Aby uzyskać prawidłowe rozwiązanie do utrwalania danych podczas odświeżania strony, zajrzyj tutaj . Aby uzyskać trwałe dane, gdy zmienia się trasa, spójrz na odpowiedź Carloscarcamo. Wszystko, czego potrzebujesz, to umieścić dane w usłudze.$scope.user = userService;
masz coś takiego:$scope.name = userService.model.name; $scope.email = userService.model.email;
. Czy to zadziała, czy zmiana widocznych zmiennych nie zmieni tego w usłudze?Trochę za późno na odpowiedź, ale właśnie zaktualizowałem skrzypce z najlepszymi praktykami
jsfiddle
źródło
updateService
należy wywołać, gdy kontroler zostanie zniszczony -$scope.$on('$destroy', function() { console.log('Ctrl destroyed'); $scope.updateServiceName($scope.name); });
$ rootScope to duża zmienna globalna, która jest odpowiednia w przypadku jednorazowych rzeczy lub małych aplikacji. Skorzystaj z usługi, jeśli chcesz hermetyzować swój model i / lub zachowanie (i ewentualnie użyć go ponownie w innym miejscu). Oprócz grupy Google opublikuj wspomniany OP, zobacz również https://groups.google.com/d/topic/angular/eegk_lB6kVs/discussion .
źródło
Angular tak naprawdę nie zapewnia tego, czego szukasz po wyjęciu z pudełka. To, co chciałbym zrobić, aby osiągnąć to, czego szukasz, to użyć następujących dodatków
Router UI i Dodatki do routera UI
Te dwie opcje zapewniają routing oparty na stanach i stany trwałe. Możesz przełączać między stanami, a wszystkie informacje zostaną zapisane, ponieważ zakres „pozostaje żywy”, że tak powiem.
Sprawdź dokumentację obu, ponieważ jest całkiem prosta, dodatki do routera interfejsu użytkownika mają również dobrą demonstrację działania lepkich stanów.
źródło
Miałem ten sam problem, oto co zrobiłem: mam SPA z wieloma widokami na tej samej stronie (bez Ajax), więc to jest kod modułu:
Mam tylko jeden kontroler do wszystkich widoków, ale problem jest taki sam jak pytanie, kontroler zawsze odświeża dane, aby uniknąć tego zachowania zrobiłem to co ludzie sugerują powyżej i stworzyłem w tym celu usługę, a następnie ją przekazuję do kontrolera w następujący sposób:
Teraz mogę wywołać funkcję aktualizacji z dowolnego z moich widoków, przekazać wartości i zaktualizować mój model, nie muszę używać interfejsu API html5 do danych trwałości (tak jest w moim przypadku, może w innych przypadkach byłoby konieczne użycie html5 api, takie jak localstorage i inne rzeczy).
źródło
Alternatywą dla usług jest wykorzystanie magazynu wartości.
W bazie mojej aplikacji dodałem to
A potem w moim kontrolerze po prostu odwołuję się do magazynu wartości. Nie sądzę, aby miało to znaczenie, jeśli użytkownik zamyka przeglądarkę.
źródło
Rozwiązanie, które będzie działać dla wielu zakresów i wielu zmiennych w tych zakresach
Ta usługa została oparta na odpowiedzi Antona, ale jest bardziej rozszerzalna i będzie działać w wielu zakresach oraz umożliwia wybór wielu zmiennych zakresu w tym samym zakresie. Używa ścieżki trasy do indeksowania każdego zakresu, a następnie nazw zmiennych zakresu do indeksowania o jeden poziom głębiej.
Utwórz usługę za pomocą tego kodu:
Dodaj ten kod do funkcji uruchamiania w module aplikacji:
Wprowadź usługę restoreScope do kontrolera (przykład poniżej):
Powyższy przykład zainicjuje $ scope.user do zapisanej wartości, w przeciwnym razie domyślnie użyje podanej wartości i zapisze ją. Jeśli strona zostanie zamknięta, odświeżona lub trasa zostanie zmieniona, bieżące wartości wszystkich zarejestrowanych zmiennych zakresu zostaną zapisane i zostaną przywrócone podczas następnej wizyty na trasie / stronie.
źródło
Możesz użyć
$locationChangeStart
zdarzenia do przechowywania poprzedniej wartości w$rootScope
usłudze lub w usłudze. Kiedy wrócisz, po prostu zainicjuj wszystkie wcześniej zapisane wartości. Oto szybkie demo przy użyciu$rootScope
.źródło