如何在不重新加载页面的情况下使用ngIf

时间:2019-12-15 12:03:58

标签: angular

我有导航栏组件,我的目标是根据用户登录显示两个不同的导航栏,即,如果用户登录,他们将看到一个导航栏;如果没有的话,另一个。我正在使用ngIf,并且一切正常,除了登录用户仍然看到未登录用户的导航栏,直到他们手动刷新页面为止。

import {Component, OnInit} from '@angular/core';
import {User} from '@models/user.model';
import {AuthenticationService} from '@services/auth.service';
import {Observable} from 'rxjs';

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
  user: User;
  authObs: Observable<User>;

  constructor(private auth_service: AuthenticationService) { }

  ngOnInit() {
    this.authObs =  this.auth_service.currentUser;
  }
<nav *ngIf="authObs | async as auth; else elseBlock" class="navbar navbar-expand-lg navbar-dark bg-dark">
  <div class="container">

    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="navbarSupportedContent">

      <ul class="navbar-nav">
        <li class="nav-item sub">
          <a class="nav-link unselectable" (click)="gt_myprofile()"><span class="icon icon-profile"></span> my
            profile</a>
        </li>
        <li class="nav-item sub">
          <a class="nav-link unselectable" (click)="gt_messages()"><span class="icon icon-message"></span> messages
            <span
              class="icon-notif"></span> </a>
        </li>
        <li class="nav-item sub">
          <a class="nav-link unselectable" (click)="gt_contacts()"><span class="icon icon-contacts"></span>
            contacts<span
              class="icon-notif"></span> </a>
        </li>
      </ul>
    </div>
  </div>
</nav>

<ng-template #elseBlock>
  <nav  class="navbar navbar-expand-lg navbar-dark bg-dark">
    <div class="container">
      <a class="navbar-brand" href="#"><img src="assets/static" alt=""></a>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
              aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <!-- start navbar-nav -->
        <ul class="navbar-nav">
          <li class="nav-item">
            <a class="nav-link" href="#">about<span class="sr-only">(current)</span></a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">cooperation</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">terms</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">contacts</a>
          </li>
        </ul>
      </div>
    </div>
</nav>
</ng-template>
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject, Observable } from 'rxjs';
import { map } from 'rxjs/operators';

import { User } from '@models/user.model';

@Injectable({ providedIn: 'root' })

export class AuthenticationService {
  private currentUserSubject: BehaviorSubject<User>;
  public currentUser: Observable<User>;

  constructor(private http: HttpClient) {
    this.currentUserSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('currentUser')));
    this.currentUser = this.currentUserSubject.asObservable();
  }

  public get currentUserValue(): User {
    return this.currentUserSubject.value;
  }
}

login(email: string, password: string) {
  return this.http.post<any>(`${environment.apiUrl}/api/auth/`, { email, password })
    .pipe(map(user => {
      // store user details and jwt token in local storage to keep user logged in between page refreshes
      localStorage.setItem('currentUser', JSON.stringify(user));
      this.currentUserSubject.next(user);
      this.currentUser = this.currentUserSubject.asObservable();
      console.log("TCL: AuthenticationService -> login -> user", user)
      return user;
    }));
}

1 个答案:

答案 0 :(得分:0)

我认为问题在于s0,s1,s3没有发出新值,否则* ngIf和异步管道使用情况看起来不错。

如何调用/使用authService更新登录信息?

如果您更新localStorage信息以反映该用户是否已登录,则应发出该主题的新值,例如:

authService

您可以在用户登录后或要更新currentUser状态时调用此方法。这取决于您的代码逻辑,但是发出新值很重要,否则您的主题将永远不会通知订户可以使用新值。


您是否尝试过调试authObs变量并将其值打印在模板中?

updateUserAuth(newValue) {
    this.currentUserSubject.next(newValue);
    this.currentUser = this.currentUserSubject.asObservable();
}

我认为您也可以跳过构造函数中的currentUser初始化(或者是否始终将用户信息存储在本地,直到显式注销为止?):

   <.. *ngIf="authObs | async as auth; else elseBlock">
     Auth: {{auth}} 

最终可以用您的代码创建一个stackBlitz示例吗?