Come memorizzo un contesto utente corrente in AngularJS?


92

Ho un AuthService, che accede a un utente, restituisce un oggetto json dell'utente. Quello che voglio fare è impostare quell'oggetto e fare in modo che tutte le modifiche si riflettano sull'applicazione (stato di accesso / disconnessione) senza dover aggiornare la pagina.

Come potrei farlo con AngularJS?

Risposte:


180

Il modo più semplice per farlo è utilizzare un servizio. Per esempio:

app.factory( 'AuthService', function() {
  var currentUser;

  return {
    login: function() { ... },
    logout: function() { ... },
    isLoggedIn: function() { ... },
    currentUser: function() { return currentUser; }
    ...
  };
});

Puoi quindi fare riferimento a questo in uno qualsiasi dei tuoi controller. Il codice seguente controlla le modifiche in un valore dal servizio (chiamando la funzione specificata) e quindi sincronizza i valori modificati nell'ambito.

app.controller( 'MainCtrl', function( $scope, AuthService ) {
  $scope.$watch( AuthService.isLoggedIn, function ( isLoggedIn ) {
    $scope.isLoggedIn = isLoggedIn;
    $scope.currentUser = AuthService.currentUser();
  });
});

E poi, ovviamente, puoi usare quelle informazioni come meglio credi; es. nelle direttive, nei modelli, ecc. Puoi ripetere questa operazione (personalizzata in base a ciò che devi fare) nei controller del menu, ecc. Sarà tutto aggiornato automaticamente quando cambi lo stato del servizio.

Qualunque cosa più specifica dipende dalla tua implementazione.

Spero che questo ti aiuti!


28
@ChrisNicola In realtà, in AngularJS tutti i servizi sono singoli. Quindi il servizio viene creato la prima volta che viene richiesto (cioè da un controller o da un altro servizio) e tutte le richieste successive restituiscono la stessa identica istanza.
Josh David Miller,

2
Potrebbe essere, ma come funzione possiamo rimuovere gli elementi interni di come archiviamo tali informazioni dall'API pubblica e nell'API privata. Ciò rende il refactoring successivo molto più semplice. Ma la funzione restituirebbe comunque un valore booleano.
Josh David Miller

7
Questa potrebbe essere una domanda stupida ... ma cosa succede se l'utente aggiorna la pagina - le informazioni di accesso sono perse?
Tomba

10
@Tomba Questa è una bella domanda. :-) Effettivamente le informazioni si perdono all'aggiornamento. Di solito, ti consigliamo di memorizzare alcune informazioni sulla sessione in un cookie. Le informazioni sulla sessione possono essere controllate anche durante la configurazione di AuthService. Questo aiuta non solo per gli aggiornamenti della pagina, ma per qualcuno che apre un collegamento in una nuova scheda.
Josh David Miller

2
@PixMach Hai ragione al 100% sulla curva di apprendimento. La tua domanda dipenderà molto dal caso specifico, ma qui ci sono alcuni schemi generali. Mantieni la separazione delle preoccupazioni: l'interfaccia utente relativa all'avvio di un accesso è separata dall'autenticazione stessa, che è separata dallo stato dell'autenticazione, che è separata da qualsiasi menu che può dipendere da detto stato. Nav / menu sono spesso gestiti al meglio da un singolo controller e gli stati annidati (a la ui-router) e le risoluzioni delle rotte sono un buon modo per mantenere asciutti i controlli di autenticazione. Quello che hai scritto sembra giusto.
Josh David Miller

5

Modificherei la buona risposta di Josh aggiungendo che, poiché un AuthService è tipicamente di interesse per chiunque (ad esempio, chiunque tranne la vista di accesso dovrebbe scomparire se nessuno è registrato), forse un'alternativa più semplice sarebbe notificare le parti interessate utilizzando $rootScope.$broadcast('loginStatusChanged', isLoggedIn);(1 ) (2), mentre le parti interessate (come i responsabili del trattamento) ascolterebbero utilizzando $scope.$on('loginStatusChanged', function (event, isLoggedIn) { $scope.isLoggedIn = isLoggedIn; }.

(1) $rootScopeessere iniettato come argomento del servizio

(2) Nota che, nel probabile caso di un'operazione di accesso asincrono, ti consigliamo di notificare ad Angular che la trasmissione cambierà le cose, includendola in un $rootScope.$apply() funzione.

Ora, parlando di mantenere il contesto utente in ogni / molti controller, potresti non essere felice di ascoltare le modifiche all'accesso in ognuno di essi e potresti preferire ascoltare solo in un controller di accesso più in alto, quindi aggiungere altri controller consapevoli dell'accesso come bambini / controller incorporati di questo. In questo modo, il controller figlio sarà in grado di vedere le proprietà $ scope genitore ereditate come il contesto dell'utente.


4
Downvoted per spiegazione errata della funzione di fabbrica. Questo malinteso è stato già affrontato in questo commento mesi prima che tu pubblicassi la tua risposta.
Rhys van der Waerden
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.