简体   繁体   English

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

[英]Angular 2 - Only display certain elements on navbar when user is logged in

I am working on my first project in Angular 2, and I am working on user authentication and features related to it. 我正在Angular 2中进行我的第一个项目,并且正在进行用户身份验证及其相关功能。 Everything is going well and the documentation/examples has served me very well so far. 一切进展顺利,到目前为止,文档/示例对我的服务很好。

Currently, I am attempting to implement the feature of only showing certain links on my site's navbar when a user is logged in, and other links when there is no user logged in. However, my current implementation does not work as intended. 当前,我正在尝试实现仅在用户登录时在网站的导航栏中显示某些链接,而在没有用户登录时在其他链接上显示某些链接的功能。但是,我当前的实现无法正常工作。 The links in my navbar only change when the page is reloaded and it finds that there is/isn't an authenticated user. 我的导航栏中的链接仅在重新加载页面并且发现有/没有经过身份验证的用户时才会更改。 The following is my current implementation: 以下是我当前的实现:

Here is my app.component.html file, it is used as a "base template" for my site: 这是我的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>

and my app.component.ts file, which is getting loggedIn from a authentication service, which basically checks localStorage for a authentication token which is from a Django Rest api that serves as my backend for authentication: 和我的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']);
  }
}

and finally, in case it is of use, the authentication service that I created to manage whether a user is logged in or not: 最后,在使用的情况下,我创建的用于管理用户是否登录的身份验证服务:

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;
    }
}

My dillema comes in when I am either logging in or logging out. 我登录或注销时都会感到不适。 Before I log in, the navbar displays only the "Register" and "Login" links. 在我登录之前,导航栏仅显示“注册”和“登录”链接。 After I log in, I am redirected to the "My Log" page, but the navbar's contents do not get updated. 登录后,我将重定向到“我的日志”页面,但是导航栏的内容不会更新。 Instead of providing links to "My Log", "My Team" and "Logout", the links for "Register" and "Login" are still present in the navbar. 导航栏中仍然存在“注册”和“登录”的链接,而不是提供指向“我的日志”,“我的团队”和“注销”的链接。 The same problem is present with logout as well. 注销也存在相同的问题。

Am I headed in the right direction with my current implementation? 我当前的实施方式是否朝着正确的方向前进? If not, is there an easy solution/anything in Angular 2 that can help me implement the feature that I have described? 如果没有,Angular 2中是否有一个简单的解决方案/功能可以帮助我实现上述功能?

You may update your code like below, 您可以像下面那样更新代码,

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
    }       
}

In your component use below, 在下面的组件使用中,

loggedIn: any;

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

and use async pipe in template bindings. 并在模板绑定中使用async pipe

Hope this helps!! 希望这可以帮助!!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM