"ОШИБКА TypeError: Невозможно прочитать свойство 'name' из undefined" Angular - PullRequest
1 голос
/ 10 февраля 2020

Я не уверен, что я здесь сделал неправильно. При попытке отобразить имя пользователя после входа в систему на панели инструментов для панели мониторинга, но при попытке вызвать созданный мной интерфейс с именем UserDetails, консоль браузера говорит, что имя UserDetails не определено. Я убедился, что UserDetails импортирован из моего другого файла.

У меня есть файл компонента ts

import { Component, OnInit } from "@angular/core";
import {
  BreakpointObserver,
  BreakpointState,
  Breakpoints
} from "@angular/cdk/layout";
import { Observable } from "rxjs";
import {
  AuthenticationService,
  UserDetails
} from "../auth/authentication.service";

@Component({
  templateUrl: "./portal.component.html",
  styleUrls: ["./portal.component.scss"]
})
export class PortalComponent {
  details: UserDetails;

  isHandset: Observable<BreakpointState> = this.breakpointObserver.observe(
    Breakpoints.Handset
  );
  constructor(
    private breakpointObserver: BreakpointObserver,
    private auth: AuthenticationService
  ) {}

  ngOnInit() {
    this.auth.profile().subscribe(
      user => {
        this.details = user;
      },
      err => {
        console.error(err);
      }
    );
  }
}

и шаблон моего компонента здесь

<mat-sidenav-container>
  <mat-sidenav
    #drawer
    mode="side"
    opened
    fixedInViewport="true"
    [attr.role]="isHandset ? 'dialog' : 'navigation'"
    [mode]="(isHandset | async)!.matches ? 'over' : 'side'"
    [opened]="!(isHandset | async)!.matches"
  >
    <span><h1>Maersk</h1></span>
    <mat-divider></mat-divider>
    <mat-nav-list>
      <ul>
        <li>
          <a routerLink="/portal/dashboard">
            <button mat-flat-button color="accent">
              DASHBOARD
            </button>
          </a>
        </li>
        <li>
          <a routerLink="/portal/orders">
            <button mat-flat-button color="accent">
              ORDERS
            </button>
          </a>
        </li>
        <li>
          <a routerLink="/portal/stats">
            <button mat-flat-button color="accent">
              STATISTICS
            </button>
          </a>
        </li>
      </ul>
    </mat-nav-list>
  </mat-sidenav>
  <mat-sidenav-content>
    <mat-toolbar>
      <mat-toolbar-row>
        <button
          type="button"
          aria-label="Toggle sidenav"
          mat-icon-button
          (click)="drawer.toggle()"
          *ngIf="(isHandset | async)!.matches"
        >
          <mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
        </button>
        <span class="right-align"></span>
        <button mat-button [matMenuTriggerFor]="menu">
          {{ details.name }}
        </button>
        <mat-menu #menu="matMenu">
          <a (click)="auth.logout()">
            <button mat-menu-item>
              LOGOUT
            </button>
          </a>
        </mat-menu>
      </mat-toolbar-row>
    </mat-toolbar>
    <router-outlet></router-outlet>
  </mat-sidenav-content>
</mat-sidenav-container>

Консоль продолжает выплевывать "ОШИБКА TypeError: Невозможно прочитать свойство 'name' из undefined". Не знаю, почему он не находит детали в файле ts компонента.


ОБНОВЛЕНИЕ:

Публикация еще некоторого кода после обнаружения самих деталей выглядит как неопределенная. Это мой вызов profile () из authentication.service.ts

public profile(): Observable<any> {
    return this.request("get", "profile");
  }

, а затем это request (), который вызывается в profile ()

private request(
    method: "post" | "get",
    type: "login" | "register" | "profile",
    user?: TokenPayload
  ): Observable<any> {
    let base;

    if (method === "post") {
      base = this.http.post("http://localhost:3000" + `/api/${type}`, user);
    } else {
      base = this.http.get("http://localhost:3000" + `/api/${type}`, {
        headers: { Authorization: `Bearer ${this.getToken()}` }
      });
    }

    const request = base.pipe(
      map((data: TokenResponse) => {
        if (data.token) {
          this.saveToken(data.token);
        }
        return data;
      })
    );

    return request;
  }

Кроме того, только в В этом случае, вот еще несколько методов, которые вызываются в request ()

private saveToken(token: string): void {
    localStorage.setItem("mean-token", token);
    this.token = token;
  }

  private getToken(): string {
    if (!this.token) {
      this.token = localStorage.getItem("mean-token");
    }
    return this.token;
  }

Все здесь работало нормально, когда дело доходило до входа пользователя в систему.

1 Ответ

2 голосов
/ 10 февраля 2020

Используйте оператор безопасной навигации внутри кнопки (где отображается имя), как показано ниже,

<button mat-button [matMenuTriggerFor]="menu">
    {{ details?.name }}
</button>
...