Почему значение не меняется на false в AuthGuard? - PullRequest
0 голосов
/ 15 октября 2018

В компоненте шаблона AppComponent, в зависимости от значения, переменная this.loggedInService.isLoggedIn переключается между методами logIn() и logout(), которые в прикладном компоненте AppComponent являются subscribe d для этих методов вуслуга LoggedinService и, в зависимости от метода, измените значение переменной на true или false.

Также в методе Guard checkLogin (url: string) Я возвращаю true или false в зависимостина значение переменной this.loggedInService.isLoggedIn.

Когда я запускаю приложение, я не могу войти в модуль, когда я нажимаю на кнопку, я могу, но когда я повторяю нажатие на кнопку «выход», я все еще могу перейти к модулю.

Как заставить переключатель на checkLogin работать так, чтобы аутентификация работала правильно и сохранить значение переключения состояния между входом и выходом при перезапуске страницы?

** AppComponent.html: **

        <li class="nav-item">
            <a class="btn btn-outline-success"
               [class.btn-outline-success]="!this.loggedInService.isLoggedIn$"
               [class.btn-outline-danger]="this.loggedInService.isLoggedIn$"
               (click)="this.loggedInService.isLoggedIn$ ? logout() : logIn()">
                {{this.loggedInService.isLoggedIn$ ? 'Exit' : 'Enter'}}
            </a>
        </li>

** AppComponent.ts **

класс экспорта AppComponent реализует OnInit {сообщение: строка;

constructor(public loggedInService: LoggedinService,
            public router: Router) {
    this.setMessage();
}

ngOnInit() {}

logIn(): void {
    this.loggedInService.login().subscribe(() => {
        if (this.loggedInService.isLoggedIn$) {
            let redirect = this.loggedInService.redirectUrl ? this.loggedInService.redirectUrl :
                '/gallery';
            this.router.navigate([redirect]);
        }
    });
}

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

}

Служба входа в систему:

export class LoggedinService {
isLoggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
isLoggedIn$: Observable<boolean> = this.isLoggedIn.asObservable();
  redirectUrl: string;

  constructor() {}

  login(): Observable < boolean > {
    return of(true).pipe(
      delay(100),
      tap(val => this.isLoggedIn.next(true))
    );
  }

  logout(): void {
    this.isLoggedIn.next(false);
  }
}

AuthGuard:

export class AuthGuard implements CanActivate {
  constructor(
    private loggedInService: LoggedinService, 
    private router: Router
  ) {}

  canActivate(next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> {
    let url: string = state.url;
    return this.loggedInService.isLoggedIn$;
  }

  checkLogin(url: string): boolean {
    if (this.loggedInService.isLoggedIn) {
      return true;
    } else {
      this.loggedInService.redirectUrl = url;
      return false;
    }
  }
}

1 Ответ

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

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

Это поведение проявляется только в Объектах, поскольку они передаются по ссылке, а НЕ по значению.

Вы можете использовать BehaviorSubject для решения этой проблемы.

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, of } from 'rxjs';
import { Router } from '@angular/router';

import { delay, tap } from 'rxjs/operators';

@Injectable()
export class LoggedinService {

  isLoggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
  isLoggedIn$: Observable<boolean> = this.isLoggedIn.asObservable();
  redirectUrl: string;

  constructor(private router: Router) { }

  login(): Observable<boolean> {
    this.isLoggedIn.next(true);
    return this.isLoggedIn$;
  }

  logout(): Observable<boolean> {
    this.isLoggedIn.next(false);
    return this.isLoggedIn$;
  }

}

Теперь вместо isLoggedIn типа boolean вы получите isLoggedIn$ типа Observable который вам нужно будет subscribe до, чтобы получить статус авторизованного пользователя.

Вам нужно будет .subscribe до this.loggedInService.login() и this.loggedInService.login() в вашем AppComponent какиз них возвращаются isLoggedIn$.Вам нужно будет создать локальное свойство isLoggedIn и присвоить ему все, что возвращается в вашем .subscribe.Затем вы можете установить текст кнопки и обработчик щелчка на основе шаблона, основанного на этом свойстве isLoggedIn.

В случае AuthGuard, поскольку охранник может вернуть Observable<boolean> или Promise<boolean> или boolean Вы можете просто return this.loggedInService.isLoggedIn$

Вот вам Sample StackBlitz для вашей ссылки.

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