Angular 2 - 仅在用户登录时在导航栏上显示某些元素

时间:2016-09-28 00:22:51

标签: authentication angular

我正在开发Angular 2中的第一个项目,我正在开发用户身份验证和与之相关的功能。到目前为止,一切进展顺利,文档/示例对我很有帮助。

目前,我正在尝试实现仅在用户登录时在我的网站导航栏上显示某些链接的功能,以及在没有用户登录时显示其他链接的功能。但是,我当前的实现无法按预期工作。我的导航栏中的链接仅在重新加载页面时发生更改,并且发现存在/不是经过身份验证的用户。 以下是我目前的实施:

这是我的app.component.html文件,它用作我网站的“基本模板”:

<nav class="navbar navbar-default navbar-fixed-top">
  <div class="container-fluid">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
      <span class="sr-only">Toggle navigation</span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="">Project Name</a>
    </div>
    <div id="navbar" class="navbar-collapse collapse">
      <ul class="nav navbar-nav">
        <li><a *ngIf="loggedIn" routerLink="my-log">My Log</a></li>
        <li><a *ngIf="loggedIn">My Team</a></li>
      </ul>
      <ul class="nav navbar-nav navbar-right">
        <li><a *ngIf="loggedIn" (click)="logout()">Logout</a></li>
        <li><a *ngIf="!loggedIn" routerLink="register">Sign Up</a></li>
        <li><a *ngIf="!loggedIn" routerLink="login">Login</a></li>
      </ul>
    </div>
  </div>
</nav>
<router-outlet></router-outlet>

和我的app.component.ts文件,它从身份验证服务获取登录,该服务基本上检查localStorage是否有来自Django Rest api的身份验证令牌,后者用作身份验证的后端:

import { Component } from '@angular/core';
import { Router } from '@angular/router';

import { AuthenticationService } from './authentication/authentication.service';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  loggedIn = false;

  constructor(private auth: AuthenticationService, private router: Router) {
    this.loggedIn = this.auth.isLoggedIn();
  }

  logout() {
    localStorage.removeItem('authToken');
    this.router.navigate(['/login']);
  }
}

最后,如果它是有用的,我创建的用于管理用户是否登录的身份验证服务:

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';

import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';


@Injectable()
export class AuthenticationService {
    private baseApiUrl = 'http://localhost:8000/api/';
    private loggedIn = false;

    constructor(private http: Http) {
        this.loggedIn = !!localStorage.getItem('authToken');
     }

    private extractData(res: Response) {
        let body = res.json();
        return body;
    }

    userLogin(username: string, password: string) {
        let url = this.baseApiUrl + 'login/';
        let body = JSON.stringify({'username': username, 'password': password});
        let headers = new Headers({'Content-Type': 'application/json'});
        let options = new RequestOptions({ headers: headers });

        return this.http.post(url, body, options).map(this.extractData);
    }

    isLoggedIn() {
        return this.loggedIn;
    }
}

当我登录或退出时,我的dillema进来了。在我登录之前,导航栏仅显示“注册”和“登录”链接。登录后,我被重定向到“我的日志”页面,但导航栏的内容没有更新。而不是提供“我的日志”,“我的团队”和“注销”的链接,“注册”和“登录”的链接仍然存在于导航栏中。注销也存在同样的问题。

我目前的实施方向是朝着正确的方向前进吗?如果没有,是否有一个简单的解决方案/ Angular 2中的任何东西可以帮助我实现我所描述的功能?

1 个答案:

答案 0 :(得分:5)

您可以更新以下代码,

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';

import { Observable } from 'rxjs/Rx';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/map';    

@Injectable()
export class AuthenticationService {
    private baseApiUrl = 'http://localhost:8000/api/';
    // change loggedIn to a subject
    private loggedIn: Subject<boolean> = new Subject<boolean>();

    // make isLoggedIn public readonly
    get isLoggedIn() {
        return this.loggedIn.asObservable();
    }
    constructor(private http: Http) {
        this.loggedIn.next(!!localStorage.getItem('authToken'));
     }

    private extractData(res: Response) {
        let body = res.json();
        return body;
    }

    userLogin(username: string, password: string) {
        let url = this.baseApiUrl + 'login/';
        let body = JSON.stringify({'username': username, 'password': password});
        let headers = new Headers({'Content-Type': 'application/json'});
        let options = new RequestOptions({ headers: headers });

        return this.http.post(url, body, options).map(this.extractData);

        // set this.loggedIn.next inside this.extractData method
    }       
}

在下面的组件使用中,

loggedIn: any;

constructor(private auth: AuthenticationService, private router: Router) {
    this.loggedIn = this.auth.isLoggedIn;
  }

并在模板绑定中使用async pipe

希望这有帮助!!