首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >无法在angular中显示用户名

无法在angular中显示用户名
EN

Stack Overflow用户
提问于 2018-07-29 03:15:22
回答 2查看 901关注 0票数 0

我已经使用jwt标记化实现了身份验证,登录后我想在导航栏上显示用户名,但它没有显示任何内容,并在控制台上给出错误"ERROR TypeError: Cannot read property ' username‘of undefined“,但在刷新页面后,它显示用户名,但在控制台上仍给出相同的错误。

以下是我的代码

NavbarComponent.ts

代码语言:javascript
复制
import { Component, OnDestroy } from '@angular/core';
import { AuthService } from '../../services/auth.service';
import { Router } from '@angular/router';
import { User } from '../../shared/user';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { AdminAuthGuard } from '../../guards/admin.auth.guard';
import { Subscription } from 'rxjs/Subscription';

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.css']
})
export class NavbarComponent {


  user$: any;

  constructor(private authService: AuthService, private router: Router, private adminGuard: AdminAuthGuard) {
    this.authService.getProfile().subscribe((user) => {
      console.log('fsdf' + user.user.email);
      this.user$ =  user.user;
    });
   }



  onLogoutClick() {
    // console.log('this.user' + this.user$.email);
    this.authService.logout();
    this.router.navigate(['/']);
  }

}

我用来打印用户名的html代码。

代码语言:javascript
复制
<nav class="navbar navbar-expand-md navbar-light bg-light fixed-top">
  
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>

  <div class="collapse navbar-collapse" id="navbarsExampleDefault">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item active">
        <a class="nav-link" routerLink="/home">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a  class="nav-link" *ngIf="!authService.loggedIn()" [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}" routerLink="/login">Login</a>
      </li>
      <li class="nav-item">
        <a  class="nav-link" *ngIf="!authService.loggedIn()" [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}" routerLink="/register">Register</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" routerLink="/shopping-cart">Shopping Cart</a>
      </li>
      
      <li *ngIf="authService.loggedIn()" ngbDropdown class="nav-item dropdown">
        <a  ngbDropdownToggle class="nav-link dropdown-toggle"  id="dropdown01" data-toggle="dropdown" aria-haspopup="true"  aria-expanded="false">{{ user$.username }}</a>
        <div ngbDropdownMenu class="dropdown-menu " aria-labelledby="dropdown01">
          <a class="dropdown-item" routerLink="/my/orders">My Orders</a>
          <a class="dropdown-item" routerLink="/profile">Profile</a>
          
          <a class="dropdown-item" routerLink="/admin/orders">Manage Orders</a>
          <a class="dropdown-item" routerLink="/admin/products">Manage Products</a>
          <button class="dropdown-item" (click)="onLogoutClick()">Logout</button>
        </div>
      </li>
    </ul>
    
  </div>
</nav>

身份验证服务代码。重点介绍getProfile()方法

代码语言:javascript
复制
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';
import { Http, Headers, RequestOptions } from '@angular/http';
// import { map } from "rxjs/operators";
// import { map } from 'rxjs/operators';

import { switchMap } from 'rxjs/operators';
import { tokenNotExpired } from 'angular2-jwt';
import { User } from '../shared/user';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/observable/of';
@Injectable()
export class AuthService {
  private subject = new Subject<any>();
  domain = 'http://localhost:3000';
  authToken;
  user;
  options;

  constructor(private http: Http) { }

  registerUser(user) {
    return this.http.post(this.domain + '/authentication/register', user).map(res => res.json());
  }

  createAuthenticationHeaders() {
    this.loadToken();
    this.options = new RequestOptions({
      headers : new Headers({
        'Content-Type': 'application/json',
        'authorization': this.authToken
      })
    });

  }

  loadToken() {
    this.authToken = localStorage.getItem('token');
  }
  checkUsername(username) {
    return this.http.get(this.domain + '/authentication/checkUsername/' + username).map(res => res.json());
  }

  checkEmail(email) {
    return this.http.get(this.domain + '/authentication/checkEmail/' + email).map(res => res.json());
  }

  login(user) {
    return this.http.post(this.domain + '/authentication/login', user).map(res => res.json());
  }



  logout() {
    this.authToken = null;
    this.user = null;
    localStorage.clear();
  }
  storeUserData(token, user) {
    localStorage.setItem('token', token);
    localStorage.setItem('user', JSON.stringify(user));
    this.authToken = token;
    this.user = user;
  }

  getProfile() {
    this.createAuthenticationHeaders();
    return this.http.get(this.domain + '/authentication/profile', this.options).map(res => res.json());
  }



  loggedIn() {
    return tokenNotExpired();
  }

}

这是http routed API,它从用Node.js编写的mongodb数据库中获取用户。关注get() for '/profile‘方法,它返回一个Observable。

代码语言:javascript
复制
const User = require('../models/user'); // Import User Model Schema

const jwt = require('jsonwebtoken');
const config = require('../config/database');

module.exports = (router) => {
  /* ==============
     Register Route
  ============== */
  router.post('/register', (req, res) => {
    // Check if email was provided
    if (!req.body.email) {
      res.json({ success: false, message: 'You must provide an e-mail' }); // Return error
    } else {
      // Check if username was provided
      if (!req.body.username) {
        res.json({ success: false, message: 'You must provide a username' }); // Return error
      } else {
        // Check if password was provided
        if (!req.body.password) {
          res.json({ success: false, message: 'You must provide a password' }); // Return error
        } else {
          // Create new user object and apply user input
          let user = new User({
            email: req.body.email.toLowerCase(),
            username: req.body.username.toLowerCase(),
            password: req.body.password
          });
          // Save user to database
          user.save((err) => {
            // Check if error occured
            if (err) {
              // Check if error is an error indicating duplicate account
              if (err.code === 11000) {
                res.json({ success: false, message: 'Username or e-mail already exists' }); // Return error
              } else {
                // Check if error is a validation rror
                if (err.errors) {
                  // Check if validation error is in the email field
                  if (err.errors.email) {
                    res.json({ success: false, message: err.errors.email.message }); // Return error
                  } else {
                    // Check if validation error is in the username field
                    if (err.errors.username) {
                      res.json({ success: false, message: err.errors.username.message }); // Return error
                    } else {
                      // Check if validation error is in the password field
                      if (err.errors.password) {
                        res.json({ success: false, message: err.errors.password.message }); // Return error
                      } else {
                        res.json({ success: false, message: err }); // Return any other error not already covered
                      }
                    }
                  }
                } else {
                  res.json({ success: false, message: 'Could not save user. Error: ', err }); // Return error if not related to validation
                }
              }
            } else {
              res.json({ success: true, message: 'Acount registered!' }); // Return success
            }
          });
        }
      }
    }
  });

  router.get('/checkEmail/:email', (req, res) => {
    if (!req.params.email) {
      res.json({ success: false, message: 'email not provided'});
    } else {
      User.findOne({ email: req.params.email}, (err, user) => {
        if (err) {
          res.json({ success: false, message: err});
        } else {
          if (user) {
            res.json({ success: false, message: 'email taken'});
          } else {
            res.json({ success: true, message: 'email available'});
          }
        }
      });
    }
  });

  router.get('/checkUsername/:username', (req, res) => {
    if (!req.params.username) {
      res.json({ success: false, message: 'username not provided'});
    } else {
      User.findOne({ username: req.params.username}, (err, user) => {
        if (err) {
          res.json({ success: false, message: err});
        } else {
          if (user) {
            res.json({ success: false, message: 'username taken'});
          } else {
            res.json({ success: true, message: 'username available'});
          }
        }
      });
    }
  });

  router.post('/login', (req, res) => {
    if (!req.body.username) {
      res.json({ success: false, message: 'No username was provided'});
    } else {
      if (!req.body.password) {
        res.json({ success: false, message: 'No password was provided'});
      } else {
        User.findOne({ username: req.body.username.toLowerCase() }, (err, user) => {
          if (err) {
            res.json({ success: false, message: err});
          } else {
            if (!user) {
              res.json({ success: false, message: 'No user exist'});
            } else {
              const validPassword = user.comparePassword(req.body.password);
              if (!validPassword) {
                res.json({ success: false, message: 'password invalid'});
              } else {
                const token = jwt.sign({userId: user._id}, config.secret, {expiresIn: '24h'});
                res.json({ success: true, message: 'Success!', token: token, user: {username: user.username}});
              }
            }
          }
        });
      }
    }
  });

// MIDDLEWARE TO INTERCEPT HEADERS
// THIS MIDDLEWARE DECRYPTS THE TOKEN
  router.use((req, res, next) => {
    const token = req.headers['authorization']; // whenever a request coming from angular2 with headers attached it is going to search fot this header
    if (!token) {
      res.json({ success: false, message: 'No token provided'});
    } else {
      jwt.verify(token, config.secret, (err, decoded) => {
        if (err) {
          res.json({ success: false, message: 'invalid token' + err});
        } else {
          req.decoded = decoded;
          next();
        }
      });
    }
  })
// ANY ROUTES COMING AFTER THIS MIDDLEWARE WILL PASS THROUGH THE SAME

// BELOW METHOD TAKES THE DECRYPTED TOKEN FIND THE USER
  router.get('/profile', (req, res) => {
    User.findOne({ _id: req.decoded.userId }).select('username email isAdmin').exec((err, user) => {
      if (err) {
        res.json({ success: false, message: err});
      } else {
        if (!user) {
          res.json({ success: false, message: 'user not found'});
        } else {
          res.json({ success: true, user: user });
        }
      }
    });
  });

  return router; // Return router object to main index.js
}

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-29 03:16:54

尝试使用safe navigation operator或*ngIf,因为您正在向您的API发出请求并异步获取数据。尝试如下所示:

代码语言:javascript
复制
   <a  ngbDropdownToggle class="nav-link dropdown-toggle"  id="dropdown01" data-toggle="dropdown" aria-haspopup="true"  aria-expanded="false">{{ user$?.username }}</a>
票数 2
EN

Stack Overflow用户

发布于 2018-07-29 05:02:24

我非常确定这会发生在您身上,因为您试图在username属性不存在时访问user$.username。为了避免这个错误,你可以使用一个已定义的类型,然后初始化,例如。

代码语言:javascript
复制
public $user: UserInterface = {
    username: ''
}

或者你是否不想使用已定义的类型,只需使用ngIf向html块添加额外的验证,例如。

代码语言:javascript
复制
<a  *ngIf="user$.username" ngbDropdownToggle class="nav-link dropdown-toggle"  id="dropdown01" data-toggle="dropdown" aria-haspopup="true"  aria-expanded="false">{{ user$.username }}</a>

顺便说一句,作为一个很好的编码实践,对于在代码和视图之间共享的方法使用公共方法声明,aot build将感谢您。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51574459

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档