仅当用户登录或注销Angular 2+时,如何显示元素?

时间:2017-10-25 04:42:55

标签: angular rxjs angular-routing angular-observable

我正在开发Angular 2+应用程序。我发现在AngularJS中实现一些相对简单的东西非常困难。

我希望我的顶部导航在用户未登录时显示 LOG IN 按钮,并在她登录时显示 LOG OUT

我一直在尝试各种各样的事情,但我无法让它正常工作。我希望它在整个应用程序中始终如一地工作,无论是否重新加载(它将isLoggedIn存储到localStorage

我目前的实施根本没有用,但我会在这里分享,所以你可以告诉我,我是否至少在正确的轨道上。

热门-navigation.component.html

<p class="nav-item my-2 my-lg-0" *ngIf="!isLoggedIn | async"><a class="nav-link" routerLink="/login" routerLinkActive="active">Login</a></p>
  <p class="nav-item my-2 my-lg-0" *ngIf="isLoggedIn | async"><a class="nav-link" routerLink="//logout" routerLinkActive="active">Logout</a></p>

热门-navigation.component.ts

export class TopNavigationComponent implements OnInit {

  @ViewChild('topnav') topnav: ElementRef;
  //isLoggedIn: boolean;

  isLoggedIn: Observable<Boolean>;

  constructor( private authService: AuthService, private logger: LoggerService ) { }

  ngOnInit() {
    this.isLoggedIn = this.authService.getIsLoggedIn();
  }

auth.service.ts

@Injectable()
export class AuthService {

  loggedIn$: Subject<Boolean> = new Subject<Boolean>();

  constructor(private logger: LoggerService) {
    let isLoggedInLocalStore = (localStorage.getItem('isLoggedIn') === 'true');
    if (!isLoggedInLocalStore) {
      isLoggedInLocalStore = false;
      localStorage.setItem('isLoggedIn', isLoggedInLocalStore.toString());
    }
  }

  getIsLoggedIn(): Observable<Boolean> {
    //return (localStorage.getItem('isLoggedIn') === 'true');
    return this.loggedIn$.asObservable();
  }

  login(): void {
    // TODO
    this.logger.log("AuthService | Login clicked...");
    localStorage.setItem('isLoggedIn', 'true');
    this.loggedIn$.next(true);
  }

  logout() {
    // TODO
    localStorage.setItem('isLoggedIn', 'false');
    this.loggedIn$.next(false);
  }

}

3 个答案:

答案 0 :(得分:1)

我不确定我的回答会对你有所帮助。为此,我创建了名为GlobalEventsManager的服务。

import { Injectable } from '@angular/core';
import { BehaviorSubject } from "rxjs/BehaviorSubject";
import { Observable } from "rxjs/Observable";

@Injectable()
export class GlobalEventsManager {

    private _showMainMenu: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null);
    public showMainMenuEmitter: Observable<boolean> = this._showMainMenu.asObservable();

    constructor() {
      this.showMainMenu(Boolean(localStorage.getItem('currentUser')));
    }

    showMainMenu(ifShow: boolean) {
      this._showMainMenu.next(ifShow);
    }


}

在此示例中,我显示/隐藏菜单取决于用户登录或注销。 你如何使用它(不是完整的类代码,只是例子):

import { GlobalEventsManager } from "../../core/_helpers/index";
export class ExampleClass implements OnInit {
   constructor(private globalEventsManager: GlobalEventsManager) {

   }

   login(): void {
       //Your code
       ...
       //Show main menu for authentificated users
       this.globalEventsManager.showMainMenu(true)
   }

   logout(): void {
      //Your code 
      ...
      //Hide main menu
      this.globalEventsManager.showMainMenu(false)
   }

}   

如何在组件中使用它(不是完整的代码,只是示例):

import { GlobalEventsManager } from '/_helpers/index';


@Component({
    selector: "main-menu",
    templateUrl: "main-menu.component.html",
})

export class MainMenuComponent  {
    showMainMenu: boolean = false;


    constructor(private globalEventsManager: GlobalEventsManager) {
        this.globalEventsManager.showMainMenuEmitter.subscribe((mode) => {
            // mode will be null the first time it is created, so you need to igonore it when null
            if (mode !== null) {
              this.showMainMenu = mode;
            }
        });
    }

    //Other code 
    ...
    ...
    ...
}

现在你有布尔showMainMenu变量取决于你的用户。

PS:您也可以将此GlobalEventsManager用于其他目的。例如。管理应该影响您的应用程序的全局事件。

PPS:我在大约1年前在stackoverflow上找到了类似的解决方案。只是我找不到链接。因此试图在这里描述解决方案。

感谢。希望它会对你有所帮助。

答案 1 :(得分:0)

您正在使用正确的方法,但稍作修改:

在你的top-navigation.component.ts中:

isLoggedIn:boolean;

constructor(private cd:ChangeDetectorRef, private authService: AuthService, private logger: LoggerService ) { 
      this.authService.getIsLoggedIn().subscribe((loggedIn:boolean) => {
      this.isLoggedIn = loggedIn;
      this.cd.markForCheck();}
}

在您的auth.service.ts中:

getIsLoggedIn(): Subject<Boolean> {
    return this.loggedIn$;
}

并删除|来自HTML的异步。

每当用户登录时,您都会发送true,从服务中抛出您的主题,并且当用户退出时,所有订阅者都会收到通知。

答案 2 :(得分:-2)

您正在考虑的是使用中央Shared Service或甚至使用Event Emitters来实现此目的。

您必须将此功能与本地存储结合使用。当用户登录时,您需要将数据保存在共享服务和本地存储中。因此,这将确保如果他注销,您可以将所有数据都存储在本地存储中,并检查用户是否已登录。

当他按下Logout按钮时从本地存储和共享服务中删除本地值。

现在,如何在此处显示“登录”和“注销”按钮,即事件发射器和共享服务将成为他们的魔力。将值添加到共享服务后,它将发出一个Observable,它将由Observing组件和Observing组件使用If和Else来显示按钮。

Working Example