【问题标题】:Reload Angular 9 component elements on data change在数据更改时重新加载 Angular 9 组件元素
【发布时间】:2020-11-07 23:15:42
【问题描述】:

我正在使用 Angular 9,我想在用户登录时动态更改菜单项的数据。但是,由于菜单与主页一起加载,因此当用户登录时,数据会更改在我手动刷新页面之前不会反映在菜单项中。我尝试使用 Renderer 2、ChangeDetectorRef 和 ElementRef,但未能自动重新加载菜单。下面我只添加相关元素,因为实际的组件代码很长。询问我是否需要了解其他信息:

HTML:

              <div class="widget-text">
                  <a mat-button [matMenuTriggerFor]="accountMenu" #accountMenuTrigger="matMenuTrigger" *ngIf="!isLoggedIn">
                    <mat-icon>person</mat-icon>
                    <span fxShow="false" fxShow.gt-sm class="flag-menu-title">Account</span>
                    <mat-icon class="mat-icon-sm caret cur-icon">arrow_drop_down</mat-icon>
                </a>
                <mat-menu #accountMenu="matMenu" [overlapTrigger]="false" xPosition="before" class="app-dropdown">
                    <span>
                        <button mat-menu-item [routerLink]="['/admin/login']" routerLinkActive="router-link-active">
                          <mat-icon >person</mat-icon>
                          <span>Login</span>
                        </button>
                        <button mat-menu-item [routerLink]="['/admin/login']" routerLinkActive="router-link-active">
                          <mat-icon>person_add</mat-icon>
                          <span>Register</span>
                        </button>
                    </span>
                </mat-menu>
                <a mat-button [matMenuTriggerFor]="profileMenu" #profileMenuTrigger="matMenuTrigger" *ngIf="isLoggedIn">
                  <mat-icon>person</mat-icon>
                  <span fxShow="false" fxShow.gt-sm class="flag-menu-title">Howdy, {{name}}</span>
                  <mat-icon class="mat-icon-sm caret cur-icon">arrow_drop_down</mat-icon>
              </a>
              <mat-menu #profileMenu="matMenu" [overlapTrigger]="false" xPosition="before" class="app-dropdown">
                  <span>
                      <button mat-menu-item [routerLink]="['/admin/profile']" routerLinkActive="router-link-active">
                        <mat-icon >person</mat-icon>
                        <span>Profile</span>
                      </button>
                      <button mat-menu-item (click)="logout()">
                        <mat-icon>warning</mat-icon>
                        <span>Logout</span>
                      </button>
                  </span>
              </mat-menu>
                  </div>

打字稿:

public name;
public isLoggedIn = false;

  constructor(public router: Router, private cartService: CartService, public sidenavMenuService:SidebarMenuService) {
    this.checkLogin();
    this.name = Cookie.get('userName');
  }

public checkLogin(): any {
    if(Cookie.get('authtoken')) {
      this.isLoggedIn = true;
    }
  }

【问题讨论】:

  • 您要更改的模板中的菜单项是什么?
  • constructor 中的任何代码移至ngOnInitngOnChange
  • @Charlie 如果变量 isLoggedIn = true 那么垫子按钮应该从 Account 更改为 Howdy, {{name}}
  • @Benny 没有改变任何东西
  • 您的 checklogin 函数在构造函数中。它应该在您的登录代码之后立即执行..

标签: javascript angular typescript angular-material angular-changedetection


【解决方案1】:

当您登录已登录的守卫(即身份验证守卫)时,您无需使事情变得复杂。

import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuardService implements CanActivate {
  
  constructor(public auth: AuthService, public router: Router , private sideMenuService: SideMenuService) {}
  
  canActivate(): boolean {
    if (!this.auth.isAuthenticated()) {
      this.sideMenuService.sideMenuData.next({...data});  // so here you can dispatch the side menu service data . 
      this.router.navigate(['dashboard']); // here after authentication it 
                                             will redirect to your dashboard 
                                             page
      return false;
     }
   return true;
   } 
 }
  
} 

因此,当您登陆仪表板页面时重定向后,在仪表板组件中,您还注入了 sideMenu 服务并订阅了 BehaviourSubject 菜单数据字段。

public name;
public isLoggedIn = false; // here you don't need to check login
                        // because you come here from auth guard
  constructor(public router: Router, private cartService: CartService, 
   public sidenavMenuService: SidebarMenuService) {
   this.checkLogin();  // same no need to check login in each 
                         component if you use auth guard 

   this.name = Cookie.get('userName');
}

public ngOnInit(){
  this.sideMenuService.sideMenuData.subscribe((data)=>{
    // hered you get the data dynamic , you can assign to any 
    // component field.
 });
}
 public checkLogin(): any {
    if(Cookie.get('authtoken')) {
    this.isLoggedIn = true;
 }

}

这就是您每次登录时发送一些动态数据时的方式,并且您的 behaviorSubject 将得到更新,并且您在 Dashboard 组件中订阅的任何位置都将获得动态数据。

希望它会有所帮助。

【讨论】:

    【解决方案2】:

    构造函数在页面创建过程中只执行一次。

    constructor(public router: Router, private cartService: CartService, public sidenavMenuService:SidebarMenuService) {
        this.checkLogin();
        this.name = Cookie.get('userName');
      }
    

    现在,根据代码,如果在构建过程中没有找到 cookie authtoken,那么您的应用无法知道它是否是由另一个(登录)进程创建的。

    您应该在登录完成后立即调用checkLogin 函数和name 赋值。

    【讨论】:

      猜你喜欢
      • 2021-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多