Angular 7:页面上显示数据,但控制台无法读取属性

问题描述 投票:0回答:3

我正在使用我正在构建的Angular 7应用程序,我在从API返回数据并将其正确地写在页面上时遇到了一些问题。

我试图遵循promises和observables的指南,但我似乎无法正确地在头文件中显示数据,或者在这种情况下让控制台停止抛出错误。我尝试使用Elvis运算符,但这只是使显示值为空而不是显示值。

resume.service.ts

export class ResumeService {
  nameURL: string = 'REDACTED';

  constructor(private http: HttpClient) { }

  getName() {
    return this.http.get(this.nameURL);
  }
}

返回this.http.get(this.nameURL);

[
  {
    name: 'My Name'
  }
]

navbar.component.ts

export class NavbarComponent implements OnInit {
  data: Name;
  reason = '';
  @ViewChild('sidenav') sidenav: MatSidenav;

  constructor(private http: HttpClient, private resumeAPI: ResumeService) {
    this.resumeAPI.getName().subscribe(res => {
      this.data = res[0];
    });
  }

  close(reason: string) {
    this.reason = reason;
    this.sidenav.close();
  }
}

export interface Name {
  name: string
}

navbar.component.html

<div>
  <a routerLink="/">
    {{ this.data.name }}
  </a>
</div>

所以,在导航栏中,我看到this(它显示我的名字,模糊的区域是 - 这是API返回的数据)

但是,在控制台中我看到以下errors(该链接有控制台错误的图片,但这是具体的:无法读取未定义的属性'name'

我知道它是在API为渲染提供数据之前抛出错误,但我不知道如何解决它,因为将HTML更改为{{this.data?。name}}会使导航栏变为空白,并且{{this.data.name?导致此错误:意外结束表达式:{{this.data.name? }}

angular promise observable angular7
3个回答
1
投票

删除HTML文件中的“this”

{{ data.name }}

0
投票

在您的情况下,this.http.get()执行异步操作。因此,在运行this.data = res[0];线之前,this.data尚未初始化并且它会抛出错误。

你只需要检查是否设置了this.data

<a routerLink="/" *ngIf="this.data">
    {{ this.data.name }}
</a>

要么

<a routerLink="/">
    {{ this.data?.name }}
</a>

但我认为第一个更有意义,因为你可能不希望在文本设置之前显示链接


要么

您可以使用async管道来使Angular处理订阅本身。

this.data = this.resumeAPI.getName().pipe(map(res => res[0]));

并在模板中

<a routerLink="/">
   {{ (this.data | async).name }}
</a>

0
投票

此问题的解决方案是使用Angular核心ChangeDetectorRef和detectChanges()。所有功劳都归功于@MullisS

在TypeScript文件中,我们更改了:import { Component, ViewChild } from '@angular/core';import { Component, ViewChild, ChangeDetectorRef } from '@angular/core';(添加了ChangeDetectorRef)。

在构造函数中,我们更改了:constructor(private resumeAPI: ResumeService) {constructor(private ref: ChangeDetectorRef, private resumeAPI: ResumeService) {

并且,在订阅功能中,我们更改了:

this.resumeAPI.getName().subscribe(res => {
  this.data = res[0];
});

this.resumeAPI.getName().subscribe(res => {
  this.data = res[0];
  this.ref.detectChanges();
});

以下是完整的代码解决方案供参考:navbar.component.html

<a routerLink="/" >
  {{ this.data?.name }}
</a>

navbar.component.html

import { Component, ViewChild, ChangeDetectorRef } from '@angular/core';
import { MatSidenav } from '@angular/material/sidenav';
import { HttpClient } from '@angular/common/http';
import { ResumeService } from '../services/resume.service';

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.scss'],
  providers: [ResumeService]
})
export class NavbarComponent {
  data: Name;
  reason = '';
  @ViewChild('sidenav') sidenav: MatSidenav;

  constructor(private ref: ChangeDetectorRef, private resumeAPI: ResumeService) {
    this.resumeAPI.getName().subscribe(res => {
      this.data = res[0];
      this.ref.detectChanges();
    });
  }

  close(reason: string) {
    this.reason = reason;
    this.sidenav.close();
  }
}

export interface Name {
  name: string
}
© www.soinside.com 2019 - 2024. All rights reserved.