2014-01-28 1 views
8

Zwei Probleme haben mich beunruhigt, wie ich Winkel gelernt haben:Wie gehe ich Seite erfrischend mit einem AngularJS Einzel Seite Anwendung

  1. Wie ich Zustand Sie wiederherstellen, wenn der Benutzer die Seite aktualisiert oder schlägt die Zurück-Taste ?

  2. Wie teile ich Daten zwischen Bereichen, die zu verschiedenen Controllern gehören?

Im Folgenden zeige ich eine einfache Lösung, die Verwendung von clientseitigen Sitzungsspeicher macht. Es ermöglicht sowohl die gemeinsame Nutzung gemeinsamer Daten als auch die automatische Wiederherstellung des Status, nachdem ein Benutzer die Seite aktualisiert oder die Zurück-Schaltfläche gedrückt hat.

Hinweis: Die Lösung unten erwies sich als notwendig, die folgende Frage zu beantworten:

How do I get the Back Button to work with an AngularJS ui-router state machine?

Antwort

5

Die Lösung hängt von der SessionService Klasse weiter unten. Die Syntax ist Kaffeescript.

SessionService Klasse

class SessionService 
    scopes:[] 

    setStorage:(key, value) -> 
     scope[key] = value for scope in @scopes 
     value = if value is undefined then null else JSON.stringify value 
     sessionStorage.setItem key, value 

    getStorage:(key)-> 
     sessionValue = sessionStorage.getItem key 
     if sessionValue == "undefined" 
      return null 
     JSON.parse sessionValue 

    register:(scope)-> 
     for key, value of sessionStorage 
      scope[key] = if value? and value != "undefined" then JSON.parse(value) else null 
     @scopes.push scope 
     scope.$on '$destroy', => 
      @scopes = @scopes.filter (s) -> s.$id != scope.$id 

    clear: -> 
     @setStorage(key, null) for key of sessionStorage 

    isAuthenticated: -> 
     @accessor 'isAuthenticated', value 

    user:(value=null) -> 
     @accessor 'user', value 

    # other storage items go here 

    accessor:(name, value)-> 
     return @getStorage name unless value? 
     @setStorage name, value 

angular 
.module 'app.Services' 
.service 'sessionService', SessionService 

SessionService Die Klasse definiert die isAuthenticated Eigenschaft (simple bool) und die user Eigenschaft (komplexes Objekt). Die Werte dieser Eigenschaften werden automatisch mit dem clientseitigen lokalen Objekt sessionStorage, das von javascript bereitgestellt wird, verknüpft/analysiert.

Sie fügen weitere Eigenschaften hinzu, wie erforderlich. Wie $rootScope fügen Sie Eigenschaften sparsam hinzu. Im Gegensatz zu $rootScope sind die Eigenschaftswerte nach einer Seitenaktualisierung oder einem Klick auf die Schaltfläche "Zurück" weiterhin verfügbar.

Der Dienst ermöglicht die Registrierung einer beliebigen Anzahl von Bereichen. Wenn ein Bereich registriert wird, werden alle gespeicherten Werte in sessionStorage automatisch diesem Bereich zugewiesen. Auf diese Weise haben alle registrierten Bereiche immer Zugriff auf alle Sitzungseigenschaften.

Wenn ein Eigenschaftswert aktualisiert wird, werden für alle registrierten Bereiche die entsprechenden Werte aktualisiert.

Wenn angular einen Bereich zerstört, wird er automatisch aus der Liste der registrierten Bereiche entfernt, um Ressourcen zu sparen.

Wenn ein Benutzer die Seite aktualisiert oder die Zurück-Taste drückt, wird die Winkelanwendung gezwungen, neu zu starten. Normalerweise würde das bedeuten, dass Sie Ihren aktuellen Zustand rekonstruieren müssten. Die SessionService erledigt dies automatisch für Sie, da für jeden Bereich die Werte aus dem lokalen Speicher wiederhergestellt werden, wenn sie während der App-Initialisierung registriert werden.

So jetzt ist es einfach, das Problem der Freigabe von Daten zwischen den Bereichen sowie das Wiederherstellen von Werten zu lösen, wenn der Benutzer aktualisiert oder die Zurück-Taste drückt.

Hier ist ein Beispiel Winkelcode, der zeigt, wie die SessionService Klasse zu verwenden ist.

Registrieren Sie einen Bereich mit SessionService in einigen Controller-

angular 
.module 'app' 
.controller 'mainCtrl', ($scope, $state, session, security) -> 
    #register the scope with the session service 
    session.register $scope 

    #hook up the 'login' method (see security service) 
    $scope.login = security.login 

    # check the value of a session property 
    # it may well be true if the page has been refreshed 
    if session.isAuthenticated 
     $state.go('home') 
    else 
     $state.go('login') 

Set Session-Werte in einem Service

class SecurityService 
    @$inject:['$http','sessionService', 'api'] 
    constructor:(@http, @session, @api) -> 

    login:(username, password) => 
     @http.get "#{@api.base}/security/login/credentials/#{username}/#{password}" 
     .success (user)=> 
      @session.isAuthenticated = true 
      @session.user = user 
     .error (ex)=> 
      # process error 

angular 
.module 'app' 
.service 'securityService', SecurityService 

Verwenden Session Werte in UI (Jade-Vorlage)

div(ng-show="isAuthenticated") 
    div Hello {{user.Name}} 
+1

gibt es eine nicht-coffescript Version von diesem? Ist das auch die einzig mögliche Lösung? Vielen Dank! – EKet

+1

Sie können das coffeeskript in Javascript und wieder zurück konvertieren: http://js2coffee.org/. Es wird bestimmt andere/bessere Lösungen geben, und zuerst nahm ich an, dass es eine einfache, eckige Art geben muss, mit einer so allgemeinen Sache wie den Zurück/Refresh-Knöpfen umzugehen. Aber ich konnte es nicht finden, also, was du hier siehst, ist meine beste, aktuelle Einstellung dafür, dass es funktioniert. Ich hoffe, dass jemand eine bessere Lösung postet. – biofractal

+18

+1 für "Warum schreiben Menschen Kaffeescript-Lösungen für eckige ???" – edzillion

0

Ich war mit dem gleichen Problem konfrontiert und entschied sich für angular Cookies verwenden, da die nur Staat, der nicht von der Vorlage über ng-init gezogen wird, ist der angemeldete Benutzer Zustand.

Ich speichere die Benutzer-ID in einem Cookie bei der Anmeldung, nachdem ich den Benutzer Modell von unserem Server erhalten habe und ich den Benutzer-ID-Cookie beim Abmelden löschen. Dann, um den eingeloggten Benutzer-Status auf einer Seite aktualisieren oder zurück Schaltfläche Ereignis wiederherstellen, haken ich die Service $locationChangeStart Ereignis. Aus meinen Experimenten wird dieses -Ereignis an dem Punkt ausgelöst, an dem sich der Standort ändert, aber bevor das Partial/Template geladen wurde. Dadurch kann der benötigte Zustand nur rechtzeitig geladen werden.

Ich bin nicht davon überzeugt, dass ich eine Race-Bedingung nicht hier haben, wie $scope.loadLoggedInUser(...) verwendet asynch $ http den benötigten Zustand zu laden, aber bisher es zuverlässig für mich gearbeitet.

$scope.$on('$locationChangeStart', function() { 
      $log.debug("locationChangeStart"); 
      if (!$scope.appCtx.models.loggedInUser) { 
       var userID = $cookies.get("userID"); 
       if (!userID) { 
        $scope.doLogout(); 
        return; 
       } 
       $scope.loadLoggedInUser(userID, true); 
      } 
     }); 
Verwandte Themen