Почему isLoggedIn, наблюдаемый в шаблоне заголовка, не обновляется при входе и выходе пользователя из системы? - PullRequest
0 голосов
/ 15 октября 2018

My AppModule импортирует CoreModule

@NgModule({
  providers: [
    LoginService
  ],
})
export class CoreModule {

, который сам обеспечивает LoginService глобально.

@Injectable()
export class LoginService {

    constructor(
        private router: Router,
        private authService: AuthService
    ) { }

    login(username: string, password: string) {
        this.authService.login(username, password).subscribe(
            response => {
                this.router.navigate(['users']); // TODO Check that all router.navigate don't use hard coded strings
            },
            error => {
                console.log(error);
            }
        );
    }

    logout() {
        this.authService.logout().subscribe(
            response => {
                this.router.navigate(['login']);
            },
            error => {
                console.log(error);
            }
        );
    }

}

Существует также AuthService, который делает серверсторона входа или выхода из системы, которая сохраняет состояние входа в систему в локальном хранилище браузера.

public isAuthenticated(): Observable<boolean> {
  if (this.tokenService.accessTokenExpired()) {
    if (this.tokenService.refreshTokenExpired()) {
      return of(false);
    } else {
      return this.refreshAccessToken()
      .pipe(
        map(response => {
          if (response) {
            return true;
          }
        }),
        catchError((error, caught) => {
          return of(false);
        })
      );
    }
  }
  return of(true);
}

Существует шаблон заголовка, который должен отображаться или не отображаться в зависимости от состояния входа в систему.

<mat-toolbar color="primary" *ngIf="isLoggedIn$ | async as isLoggedIn">

Этот компонент заголовка сохраняет зарегистрированное состояние.

  isLoggedIn$: Observable<boolean>;

  ngOnInit() {
    this.isLoggedIn$ = this.authService.isAuthenticated();
  }

  logout(): void {
    this.loginService.logout();
  }

Навигация ведет себя хорошо, но шаблон заголовка нуждается в обновлении страницы для синхронизации с зарегистрированным состоянием.

ЭтоПохоже, что isLoggedIn наблюдаемый в шаблоне заголовка не обновляется при изменении состояния входа в систему.

Код был очищен от шума.

РЕДАКТИРОВАТЬ: я обхожу проблемупропуская путь ngIf и используя несколько макетов.

const routes: Routes = [
  {
    path: '',
    component: LoginLayoutComponent,
    children: [
      {
        path: '',
        redirectTo: 'login',
        pathMatch: 'full'
      },
      {
        path: 'login',
        component: LoginComponent
      }
    ]
  },
  {
    path: '',
    component: HomeLayoutComponent,
    canActivateChild: [AuthGuardService],
    children: [
      {
        path: 'users',
        component: UsersComponent,
      },
      {
        path: 'detail/:id',
        component: UserComponent,
      },
      {
        path: 'dashboard',
        component: DashboardComponent,
        data: {
          expectedRole: 'admin'
        }
      },
      {
        path: 'home',
        loadChildren: './views/home/home.module#HomeModule',
        data: {
          preload: true,
          delay: false
        }
      },
      {
        path: 'error',
        component: ErrorComponent
      },
    ]
  },
];

A login макет:

@Component({
  selector: 'app-login-layout',
  template: `<router-outlet></router-outlet>`
})
export class LoginLayoutComponent { }

и макет home:

@Component({
  selector: 'app-home-layout',
  templateUrl: './home.layout.component.html'
})
export class HomeLayoutComponent { }

со своим шаблоном:

<mat-sidenav-container class="example-container">
  <mat-sidenav #drawer mode="side" opened role="navigation">
    <mat-nav-list>
      <a mat-list-item routerLink='/first'>First Component</a>
      <a mat-list-item routerLink='/second'>Second Component</a>
    </mat-nav-list>
  </mat-sidenav>
  <mat-sidenav-content>
    <app-header></app-header>
  </mat-sidenav-content>
  <router-outlet></router-outlet>
</mat-sidenav-container>

1 Ответ

0 голосов
/ 15 октября 2018

Я вижу, что есть проблема с isAuthenticated.Он всегда возвращает новый Observable каждый раз.У вас должен быть один Observable, через который можно уведомить все Subscription.

AuthService

    private authSubject = new BehaviorSubject<boolean>(false);
    private isLoggedIn$ = this.authSubject.asObservable();

    updateLoggedInState(status: boolean){
        this.authSubject.next(status);
    }

    public isAuthenticated(): Observable<boolean> {
         return this.isLoggedIn$;
    }

LoginService

@Injectable()
export class LoginService {

    constructor(
        private router: Router,
        private authService: AuthService
    ) { }

    login(username: string, password: string) {
        this.authService.login(username, password).subscribe(
            response => {
                this.router.navigate(['users']); // TODO Check that all router.navigate don't use hard coded strings
             this.authService.updateLoggedInState(true);
            },
            error => {
                console.log(error);
                this.authService.updateLoggedInState(false);
            }
        );
    }

    logout() {
        this.authService.logout().subscribe(
            response => {
                this.router.navigate(['login']);
                this.authService.updateLoggedInState(false);
            },
            error => {
                console.log(error);
            }
        );
    }

}

Примечание: я сделалне прикрывайте токен, но вы можете справиться с ним так, как делаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...