登录后无法更新标头组件

时间:2019-08-29 18:29:32

标签: angular typescript authentication rxjs

我正在用Angular 8编写Web应用程序。

我有标题和登录页面。我想在登录后更新标题,以显示有关当前登录用户的信息。我正在使用BehaviourSubject来执行此操作,但这不起作用。

这是我的身份验证服务,位于BehaviorSubject

@Injectable()
export class AuthService {

  private readonly GRANT_TYPE = 'password';

  logged: BehaviorSubject<UserDataModel> = new BehaviorSubject<UserDataModel>(null);

  //private auth$: Observable<Auth>;

  constructor(private httpClient: HttpClient, private router: Router) { }

  login(credentials: CredentialsModel) {
    this.httpClient.post('http://localhost:8080/api/oauth/token',
      this.prepareParams(credentials),
      { headers: this.prepareHeaders() })
      .subscribe(token => {
        let userData = new UserDataModel();
        userData.token = token['access_token'];
        this.getUserInfo(userData);
      });



    //this.saveAuth();
  }

  autoLogin() {
    const userData = JSON.parse(localStorage.getItem('user'));
    if (!userData) {
      return;
    }


    if (userData.token) {
      this.logged.next(userData);
    }
  }

  private prepareHeaders(): HttpHeaders {
    let headers = new HttpHeaders();
    headers = headers.append('Authorization', 'Basic ' + btoa('frontendClientId:frontendClientSecret'));
    headers = headers.append('Content-Type', 'application/x-www-form-urlencoded');
    return headers;
  }

  private prepareParams(credentials: CredentialsModel) {
    let params = new HttpParams();
    params = params.append('username', credentials.username);
    params = params.append('password', credentials.password);
    params = params.append('grant_type', this.GRANT_TYPE);
    return params;
  }

  private getUserInfo(userData: UserDataModel) {
    this.httpClient.get('http://localhost:8080/api/user/user/current',
      {headers: new HttpHeaders().append('Authorization', 'Bearer ' + userData.token)})
      .subscribe(data => {
        userData.email = data['name'];
        userData.role = data['authorities'][0]['authority'];
        this.saveUser(userData);
        this.logged.next(userData);
        this.router.navigate(['../']);
      })
  }
private saveUser(userData: UserDataModel) {
        localStorage.setItem('user', JSON.stringify(userData))
  }
}

我的标头组件是我从身份验证服务中订阅BehaviorSubject的

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit, OnDestroy, DoCheck {

  loggedIn: boolean = false;
  username: string ='';
  private subscriptions: Subscription[] = [];

  constructor(private authService: AuthService) { }

  ngOnInit() {
    this.subscriptions.push(this.authService.logged.subscribe(this.onLogged));
  }

  ngDoCheck(): void {
    this.authService.autoLogin();
  }

  onLogout() {
    this.loggedIn = false;
  }

  onLogged(userData: UserDataModel) {
    if(userData) {
      this.loggedIn = true;
      this.username = userData.email;
    }
  }

  ngOnDestroy(): void {
    this.subscriptions.forEach(sub => sub.unsubscribe());
  }

}

一些HTML代码在登录后不会更新:

<div class="header-actions" *ngIf="!loggedIn">
    <a routerLink="/login" class="nav-link nav-icon-text">
      <clr-icon shape="user"></clr-icon>
      <span class="nav-text">Zaloguj się</span>
    </a>
    <a href="" class="nav-link nav-icon-text">
      <clr-icon shape="plus"></clr-icon>
      <span class="nav-text">Zarejestruj się</span>
    </a>
  </div>

  <div class="header-actions" *ngIf="loggedIn">
    <clr-dropdown>
      <button class="nav-text" clrDropdownTrigger>
        {{username}}
        <clr-icon shape="caret down"></clr-icon>
      </button>
      <clr-dropdown-menu *clrIfOpen clrPosition="bottom-right">
        <a routerLink="#" clrDropdownItem>Profil</a>
        <a routerLink="#" clrDropdownItem (click)="onLogout()">Wyloguj</a>
      </clr-dropdown-menu>
    </clr-dropdown>
  </div>

在登录组件中,我从auth.service调用方法“ login”,并且可以正常运行,它可以正确导航到仪表板,但没有更新的标题。

你知道我在做什么错吗?

1 个答案:

答案 0 :(得分:0)

我认为预订“ this.onLogged”的以下行存在问题:

  ngOnInit() {
    this.subscriptions.push(this.authService.logged.subscribe(this.onLogged));
  }

此处,当观察者方法-this.onLogged-被注册为可观察时,它将释放方法范围(即this上下文)。因此,Observable无法调用this.isLogged方法。将其更改为以下内容,它必须可以工作:

  ngOnInit() {
    this.subscriptions.push(this.authService.logged.subscribe((value) => {
            this.onLogged(value);
    }));
  }