我正在使用我正在构建的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? }}
删除HTML文件中的“this”
{{ data.name }}
在您的情况下,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>
此问题的解决方案是使用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
}