如何从Angular中的订阅中重新加载信息?

勇敢的水獭

在我的导航栏中,有一个用于登录和用户选项的下拉菜单。使用ngIf我显示并隐藏每个菜单。例如,当用户未登录时,将显示以下内容:

但是,当某些用户登录后,我将显示以下内容:

我通过向后端询问令牌是否有效以及是否已记录用户来完成此操作。我使用订阅来完成。问题是,当我单击“登录”或“退出”时,组件不会重新加载。我需要重新加载页面才能正常工作。在不重新加载所有页面的情况下从订阅中获取新值的最佳方法是什么?因为我不认为重新加载所有页面对于用户来说是一个很好的体验。

这是我的代码:

navbar.component.html

<ul class="navbar-nav mr-right py-0">
    <li *ngIf="!isLogged; else elseBlock" class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
            Sign in or register
        </a>
        <div class="dropdown-menu p-3 dropdown-menu-right">
            <app-login></app-login>
        </div>
    </li>
    <ng-template #elseBlock>
        <li class="nav-item dropdown">
            <a class="nav-link py-0" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <img src="{{avatarUrl}}" class="rounded-circle d-inline-block p-0 profile-img mx-3" alt="{{username}} avatar">
                <span class="dropdown-toggle p-0 m-0 align-middle">{{username}}</span>
            </a>
            <ul class="dropdown-menu-right dropdown-menu" aria-labelledby="dropdownMenuLink">
                <li><span class="dropdown-item clickable" (click)="goToProfile()">Profile</span></li>
                <li><span class="dropdown-item clickable" (click)="logout()">Sign out</span></li>
            </ul>
        </li>
    </ng-template>
</ul>

navbar.component.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { AccountService } from '../account/account.service';
import { AuthService } from '../auth/auth.service';

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit {
  
  isLogged: boolean;
  avatarUrl: string;
  username: string;
  isLogged_subscription: Subscription;
  avatar_subscription: Subscription;
  username_subscription: Subscription;

  constructor(private authService: AuthService, private accountService: AccountService, private router: Router) { }

  ngOnInit(): void {
    this.isLogged_subscription = this.authService.isLogged().subscribe(
      value => {
        this.isLogged = value;
      }
    );

    this.avatar_subscription = this.accountService.getAvatar().subscribe(
      value => {
        this.avatarUrl = value;
      }
    );
    this.username_subscription = this.accountService.getUsername().subscribe(
      value => {
        this.username = value;
      }
    );
  }

  logout(): void {
    this.authService.logout();
  }

  goToProfile(): void {
    this.router.navigateByUrl('/profile')
  }
}

身份验证服务

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { tap } from 'rxjs/operators';
import { Observable, BehaviorSubject } from 'rxjs';
import { UserI } from '../models/user';
import { ServerResponseI } from '../models/server-response';
import { environment } from '../../environments/environment';

@Injectable({
  providedIn: 'root'
})

export class AuthService {
  constructor(private httpClient: HttpClient) { }

  register(user: UserI): Observable<ServerResponseI> {
    return this.httpClient.post<ServerResponseI>(`${environment.apiBase}/account/register`, user).pipe(
      tap(
        (res: ServerResponseI) => {
          if(res){
            this.saveToken(res.token, res.expiry)
          }
        }
      )
    );
  }

  login(user: UserI): Observable<ServerResponseI> {
    return this.httpClient.post<ServerResponseI>(`${environment.apiBase}/account/get_token/`, user).pipe(
      tap(
        (res: ServerResponseI) => {
          if(res){
            this.saveToken(res.token, res.expiry)
          }
        }
      )
    );
  }

  isLogged(): Observable<boolean> {
    return this.httpClient.get<boolean>(`${environment.apiBase}/account/is_logged/`);
  }

  logout(): void{
    localStorage.removeItem("ACCESS_TOKEN");
    localStorage.removeItem("EXPIERES_IN");
  }

  private saveToken(token: string, expiresIn: string): void {
    localStorage.setItem("ACCESS_TOKEN", token);
    localStorage.setItem("EXPIERES_IN", expiresIn);
  }
}

弗拉德伦·捷列申科

您需要重新加载页面以查看更改的原因是因为您仅更新了ngOnInit中的“ isLogged”变量。

我将从注销开始,因为我看不到登录组件的代码。

最简单的解决方案如下所示:

logout(): void {
    this.authService.logout();
    this.isLogged = false;
}

如果您想通过询问您的后端来确保该用户已注销,则可以这样做:

logout(): void {
    this.authService.logout();
    this.updateLoginStatus();
}

// extracting this logic into a separate function gives us an ability 
// to use it here and in ngOnInit
updateLoginStatus(): void {
    // no need to save subscription if we don't plan to unsubscribe later
    this.authService.isLogged().subscribe(value => this.isLogged = value)
}

要在登录后更新组件,可以在登录组件中创建一个事件发射器,并在导航栏中绑定到它,如下所示:

export class LoginComponent {
    @Output() loggedIn = new EventEmitter()

    // function that handles click on "Log In" button
    buttonHandler() {
        // ... some of your login
      
       this.loggedIn.emit()
    }
}

之后,您需要像下面这样在navbar.component.html中监听此事件:

<app-login (loggedIn)="updateLoginStatus()"></app-login>

或更简单的版本:

<app-login (loggedIn)="isLogged = true"></app-login>

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在 Angular 中重新执行订阅的 Observable

来自分类Dev

在Angular中重新加载图像

来自分类Dev

在Angular中重新加载数据

来自分类Dev

如何在Angular中重新加载可观察的http?

来自分类Dev

Spring MVC:如何从Thymeleaf每个页面的数据库中重新加载登录的用户信息?

来自分类Dev

Swift-使用viewDidAppear中的新信息重新加载UIPageViewController

来自分类Dev

在 Angular 2 中重新加载组件

来自分类Dev

如何强制Meteor重新加载订阅?

来自分类Dev

Angular:如何更改订阅中的收益?

来自分类Dev

如何防止 Angular 中的多个订阅调用?

来自分类Dev

如何在 Angular 中订阅服务

来自分类Dev

如何在AngularJS中重新加载指令?

来自分类Dev

如何在jQuery中重新加载multiDatesPicker

来自分类Dev

如何从ArrayAdapter中的onClickListener重新加载活动

来自分类Dev

如何禁用流星中的实时重新加载?

来自分类Dev

如何在Ubuntu中重新加载终端?

来自分类Dev

如何在WPF中重新加载DataGrid

来自分类Dev

UICollectionView如何从委托中重新加载数据

来自分类Dev

如何在LibreOffice中重新加载字体

来自分类Dev

如何在 TableView 中重新加载数据

来自分类Dev

如何在 SpriteKit 中重新加载 GameScene

来自分类Dev

如何防止在骆驼中重新加载 javascript?

来自分类Dev

如何在Angular中重新加载时在视图控制器中重新初始化$ scope变量?

来自分类Dev

如何在Angular 8中仅重新加载或刷新子组件

来自分类Dev

如何在不重新加载页面的情况下“刷新”Angular 中的组件?

来自分类Dev

如何在 angular 2+ 中重新加载/刷新以前的 url?

来自分类Dev

如何对表中的信息进行重新排序/如何压缩表中的信息

来自分类Dev

在 ANGULAR 中订阅中的数据数组更改后,组件 (AngularMatDataTable) 不会重新呈现?

来自分类Dev

在Angular 9中,如何在父级通过Observable加载数据后重新加载子级组件?

Related 相关文章

  1. 1

    如何在 Angular 中重新执行订阅的 Observable

  2. 2

    在Angular中重新加载图像

  3. 3

    在Angular中重新加载数据

  4. 4

    如何在Angular中重新加载可观察的http?

  5. 5

    Spring MVC:如何从Thymeleaf每个页面的数据库中重新加载登录的用户信息?

  6. 6

    Swift-使用viewDidAppear中的新信息重新加载UIPageViewController

  7. 7

    在 Angular 2 中重新加载组件

  8. 8

    如何强制Meteor重新加载订阅?

  9. 9

    Angular:如何更改订阅中的收益?

  10. 10

    如何防止 Angular 中的多个订阅调用?

  11. 11

    如何在 Angular 中订阅服务

  12. 12

    如何在AngularJS中重新加载指令?

  13. 13

    如何在jQuery中重新加载multiDatesPicker

  14. 14

    如何从ArrayAdapter中的onClickListener重新加载活动

  15. 15

    如何禁用流星中的实时重新加载?

  16. 16

    如何在Ubuntu中重新加载终端?

  17. 17

    如何在WPF中重新加载DataGrid

  18. 18

    UICollectionView如何从委托中重新加载数据

  19. 19

    如何在LibreOffice中重新加载字体

  20. 20

    如何在 TableView 中重新加载数据

  21. 21

    如何在 SpriteKit 中重新加载 GameScene

  22. 22

    如何防止在骆驼中重新加载 javascript?

  23. 23

    如何在Angular中重新加载时在视图控制器中重新初始化$ scope变量?

  24. 24

    如何在Angular 8中仅重新加载或刷新子组件

  25. 25

    如何在不重新加载页面的情况下“刷新”Angular 中的组件?

  26. 26

    如何在 angular 2+ 中重新加载/刷新以前的 url?

  27. 27

    如何对表中的信息进行重新排序/如何压缩表中的信息

  28. 28

    在 ANGULAR 中订阅中的数据数组更改后,组件 (AngularMatDataTable) 不会重新呈现?

  29. 29

    在Angular 9中,如何在父级通过Observable加载数据后重新加载子级组件?

热门标签

归档