La aplicación My Angular 2 tiene una función de cierre de sesión. Queremos evitar recargar una página si podemos (es decir document.location.href = '/'; ), pero el proceso de cierre de sesión debe restablecer la aplicación para que cuando otro usuario inicie sesión no haya datos residuales de la sesión anterior.
Aquí está nuestro archivo main.ts:
import 'es6-shim/es6-shim'; import './polyfills'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { ComponentRef, enableProdMode } from '@angular/core'; import { environment } from '@environment'; import { AppModule } from './app/app.module'; if (environment.production === true) { enableProdMode(); } const init = () => { platformBrowserDynamic().bootstrapModule(AppModule) .then(() => (<any>window).appBootstrap && (<any>window).appBootstrap()) .catch(err => console.error(err)); }; init(); platformBrowserDynamic().onDestroy(() => { init(); });Puede ver que intento llamar al método init() cuando se destruye la aplicación. El método de cierre de sesión en nuestro user-authentication.service inicia la destrucción:
logout() { this.destroyAuthToken(); this.setLoggedIn(false); this.navigateToLogin() .then(() => { platformBrowserDynamic().destroy(); }); }Esto da el siguiente error:
El selector "raíz de la aplicación" no coincidió con ningún elemento
Cualquier ayuda apreciada.
Terminé resolviendo esto al final. Esto podría hacerse de manera más simple que mi implementación, pero quería mantener el arranque en main.ts en lugar de pegarlo en el servicio que solicita el reinicio.
main.ts ) se comuniquen: boot-control.ts :
import { Observable } from 'rxjs/Observable'; import { Subject } from 'rxjs/Subject'; export class BootController { private static instance: BootController; private _reboot: Subject<boolean> = new Subject(); private reboot$ = this._reboot.asObservable(); static getbootControl() { if (!BootController.instance) { BootController.instance = new BootController(); } return BootController.instance; } public watchReboot() { return this.reboot$; } public restart() { this._reboot.next(true); } }main.ts para suscribirse a la solicitud de reinicio: main.ts :
import { enableProdMode, NgModuleRef, NgModule } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; import { BootController } from './boot-control'; if (environment.production) { enableProdMode(); } const init = () => { platformBrowserDynamic().bootstrapModule(AppModule) .then(() => (<any>window).appBootstrap && (<any>window).appBootstrap()) .catch(err => console.error('NG Bootstrap Error =>', err)); } // Init on first load init(); // Init on reboot request const boot = BootController.getbootControl().watchReboot().subscribe(() => init()); user-auth.service.ts :
import { BootController } from '@app/../boot-control'; import { Injectable, NgZone } from '@angular/core'; @Injectable() export class UserAuthenticationService { constructor ( private ngZone: NgZone, private router: Router ) {...} logout() { // Removes auth token kept in local storage (not strictly relevant to this demo) this.removeAuthToken(); // Triggers the reboot in main.ts this.ngZone.runOutsideAngular(() => BootController.getbootControl().restart()); // Navigate back to login this.router.navigate(['login']); } }El requisito de NgZone es evitar el error:
Se esperaba que no estuviera en Angular Zone, ¡pero lo está!
Me encontré con el mismo problema. Una forma más sencilla es usar location.reload()
La función en su App.component que se llama cuando el usuario hace clic en el botón de cierre de sesión debería verse así.
logout() { //Auth Logout service call this.auth.logout(); //Router Navigation to Login Page this.router.navigate(['login']); //Reload Angular to refresh components and prevent old data from loading up for a //another user after login. This especially applies lazy loading cases. location.reload(); }