Angular Httpclient 服务返回数据,但数据打印失败。如何强制等待直到订阅完成
Angular Httpclient service returning data, but printing of the data fails. How to force to await until subscription is finished
我正在构建会员管理应用程序。
我有一个组件可以打印成员的详细信息。
该组件注入了 2 个服务,一个用于检索会员详细信息,另一个用于检索所有国家/地区描述的数组。
我想根据memberdetails中存储的countryid解析国家。
member-details.component.ts:
memberDetails: Observable<MemberDetailsModel>;
memberDetailsData: MemberDetailsModel;
countryList: Country[] = new Array();
memberid: number;
inputsMemberDisabled: boolean;
constructor(private route: ActivatedRoute, private memberService: MemberService, private globalDataService: GlobalDataService, private router: Router) {
}
ngOnInit() {
this.inputsMemberDisabled = true;
this.memberid = this.route.snapshot.params['id'];
console.log('calling getCountryList: ' + this.countryList);
this.countryList = this.globalDataService.getCountryList();
this.getMemberDetails();
}
getMemberDetails() {
this.memberService.getMemberDetails(this.memberid).subscribe(response => {
this.memberDetails= response;
this.memberDetailsData = response;
});
console.log("getMemberDetails() countrylist: "+ this.countryList)
}
mapCountry(id: number): Country {
console.log('mapCountry: ' + this.countryList);
for (var i = 0, len = this.countryList.length; i < len; i++) {
let country = this.countryList.pop();
if (id === country.id) {
return country;
}
}
return new Country();
到目前为止,检索 member-details 工作正常。但我不能解决这个国家。它说未定义!
member-details.component.ts(第 21 行 --)
如果我检查 global-data 服务的输出,我可以看到正在检索国家 Objects。
我假设 html-component 试图在 global-data 服务中的 Observable 完成之前渲染国家(至少控制台日志在 member-details 中给我空数组)。 component.ts)
global-data-service.ts
country: Observable<Country[]>;
countryList: Country[] = [];
constructor(private http: HttpClient) {
}
getCountryList(): Country[] {
if (this.countryList.length < 1) {
console.log("<1");
this.initializeCountryList().subscribe((res => {
console.log('countrylist result: ' + res);
this.countryList = res;
console.log('countrylist result2: ' + res);
}));
}
return this.countryList
}
initializeCountryList(): Observable<Country[]> {
if (this.countryList.length < 1) {
//return this.http.get(`${this.baseUrl}/countrylist`).pipe(map(res => res as Country[]
return this.http.get(`${this.baseUrl}/countrylist`).pipe(map(res => res as Country[]));
}
Country.ts:
export class Country {
id: number;
country: string; //This is the data I want to get
alpha2Code: string;
alpha3Code: string;
numericcode: string;
}
我真的很沮丧,因为我已经在一个多星期内尝试了多种方法 :) 但没有成功。
感谢您的建议。
编辑:
MemberDetailsModel:
import {Memberstate} from "./memberstate";
import {Member} from "./member";
import {Contactinformation} from "./contactinformation";
import {Paymentinformation} from "./paymentinformation";
export class MemberDetailsModel {
member: Member;
state: Memberstate;
contactinformations: Contactinformation[];
paymentinformation: Paymentinformation;
}
成员:
import { Membertype} from "../enums/membertype.enum";
export class Member {
//properties from mm_mem
ber
id: number;
memberid: number;
mainmemberid: number;
membertype: Membertype;
firstname: string;
surname: string;
birthdate: Date;
nationality1id: number;
nationality2id?: number;
subscriptiondate?: Date;
recorddate?: Date;
defaultlanguage:String;
billcategory: String;
comment?: String;
}
编辑2:
member-details.component.html:
<mat-card class="example-card">
<mat-card-header>
<div mat-card-avatar>
<i class="material-icons md-36">
face
</i>
</div>
<mat-card-title>Persönliche Daten</mat-card-title>
<mat-card-subtitle>Stammdaten des Mitglieds</mat-card-subtitle>
<div>
<i class="material-icons">
edit
</i>
<i class="material-icons">
save
</i>
</div>
</mat-card-header>
<mat-card-content>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Vorname" required [(ngModel)]="memberDetailsData.member.firstname" name="firstname">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Nachname" value="{{memberDetailsData.member.surname}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="true" matInput placeholder="MitgliedsNr." value="{{memberDetailsData.member.memberid}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Mitgliedsart" value="{{memberDetailsData.member.membertype}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Hauptmitglied" value="{{memberDetailsData.member.mainmemberid}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Geburtsdatum" value="{{memberDetailsData.member.birthdate | date}}">
</mat-form-field>
<!--mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Nationalität 1" value="{{mapCountry(memberDetailsData.member.nationality1id).country}}">
</mat-form-field-->
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Nationalität 1" value="{{memberDetailsData.member.nationality1id}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Nationalität 2" value="{{memberDetailsData.member.nationality2id}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Anmeldedatum" value="{{memberDetailsData.member.subscriptiondate | date}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Erfassungsdatum" value="{{memberDetailsData.member.recorddate | date}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Bevorzugte Sprache" value="{{memberDetailsData.member.defaultlanguage}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Rechnungskategorie" value="{{memberDetailsData.member.billcategory}}">
</mat-form-field>
<mat-form-field class="example-full-width">
<textarea [disabled]="inputsMemberDisabled" matInput placeholder="Kommentar" value="{{memberDetailsData.member.comment}}"></textarea>
</mat-form-field>
</mat-card-content>
<mat-card-actions>
<button mat-raised-button color="primary" [disabled]="!inputsMemberDisabled" (click)="toggleDisabledInputs()">Bearbeiten</button>
<button mat-button mat-raised-button color="warn" [disabled]="inputsMemberDisabled" (click)="updateMemberInformation()">Speichern</button>
</mat-card-actions>
</mat-card>
- 在
global-data-service
服务的 getCountryList()
函数中,您正在 returning 一个 Country
的普通数组,但它是从 Observable 内部检索的。 return 服务中的可观察值也会更好地为您服务。这样,我们可以确保 member-details
组件中的 this.countryList
变量被分配了正确的值。
全局数据-service.ts
getCountryList(): Observable<Country[]> {
const result = Subject<Country[]>();
if (this.countryList.length < 1) {
this.initializeCountryList().subscribe(
res => {
this.countryList = res;
result.next(res);
}
);
}
return result.asObservable();
}
成员-details.component.ts
ngOnInit() {
this.inputsMemberDisabled = true;
this.memberid = this.route.snapshot.params['id'];
this.globalDataService.getCountryList().subscribe(countries => { this.countryList = countries });
this.getMemberDetails();
}
- 在 HTML 模板中,使用 optional chaining operator (
?.
) 以确保在访问变量的属性之前先定义该变量。因此,将 memberDetailsData.member
的所有实例替换为 memberDetailsData?.member
。这相当于在访问它的属性之前检查 memberDetailsData
是否被定义。如果您需要检查子属性是否存在,您可以继续 memberDetailsData?.member?.firstname
.
您可以在打印数据的模板部分使用 *ngIf
指令来检查数据是否已设置。如果设置它将显示数据,否则该块将不会在 DOM 中呈现。喜欢
<div *ngIf = "memberDetailsData">
<!-- Template part goes here -->
</div>
或者您可以在访问对象的成员时使用三元运算。
memberDetailsData?.member
同时将值分配给输入字段。
希望能解决您的问题
我正在构建会员管理应用程序。
我有一个组件可以打印成员的详细信息。
该组件注入了 2 个服务,一个用于检索会员详细信息,另一个用于检索所有国家/地区描述的数组。
我想根据memberdetails中存储的countryid解析国家。
member-details.component.ts:
memberDetails: Observable<MemberDetailsModel>;
memberDetailsData: MemberDetailsModel;
countryList: Country[] = new Array();
memberid: number;
inputsMemberDisabled: boolean;
constructor(private route: ActivatedRoute, private memberService: MemberService, private globalDataService: GlobalDataService, private router: Router) {
}
ngOnInit() {
this.inputsMemberDisabled = true;
this.memberid = this.route.snapshot.params['id'];
console.log('calling getCountryList: ' + this.countryList);
this.countryList = this.globalDataService.getCountryList();
this.getMemberDetails();
}
getMemberDetails() {
this.memberService.getMemberDetails(this.memberid).subscribe(response => {
this.memberDetails= response;
this.memberDetailsData = response;
});
console.log("getMemberDetails() countrylist: "+ this.countryList)
}
mapCountry(id: number): Country {
console.log('mapCountry: ' + this.countryList);
for (var i = 0, len = this.countryList.length; i < len; i++) {
let country = this.countryList.pop();
if (id === country.id) {
return country;
}
}
return new Country();
到目前为止,检索 member-details 工作正常。但我不能解决这个国家。它说未定义!
member-details.component.ts(第 21 行 --)
如果我检查 global-data 服务的输出,我可以看到正在检索国家 Objects。 我假设 html-component 试图在 global-data 服务中的 Observable 完成之前渲染国家(至少控制台日志在 member-details 中给我空数组)。 component.ts)
global-data-service.ts
country: Observable<Country[]>;
countryList: Country[] = [];
constructor(private http: HttpClient) {
}
getCountryList(): Country[] {
if (this.countryList.length < 1) {
console.log("<1");
this.initializeCountryList().subscribe((res => {
console.log('countrylist result: ' + res);
this.countryList = res;
console.log('countrylist result2: ' + res);
}));
}
return this.countryList
}
initializeCountryList(): Observable<Country[]> {
if (this.countryList.length < 1) {
//return this.http.get(`${this.baseUrl}/countrylist`).pipe(map(res => res as Country[]
return this.http.get(`${this.baseUrl}/countrylist`).pipe(map(res => res as Country[]));
}
Country.ts:
export class Country {
id: number;
country: string; //This is the data I want to get
alpha2Code: string;
alpha3Code: string;
numericcode: string;
}
我真的很沮丧,因为我已经在一个多星期内尝试了多种方法 :) 但没有成功。
感谢您的建议。
编辑: MemberDetailsModel:
import {Memberstate} from "./memberstate";
import {Member} from "./member";
import {Contactinformation} from "./contactinformation";
import {Paymentinformation} from "./paymentinformation";
export class MemberDetailsModel {
member: Member;
state: Memberstate;
contactinformations: Contactinformation[];
paymentinformation: Paymentinformation;
}
成员:
import { Membertype} from "../enums/membertype.enum";
export class Member {
//properties from mm_mem
ber
id: number;
memberid: number;
mainmemberid: number;
membertype: Membertype;
firstname: string;
surname: string;
birthdate: Date;
nationality1id: number;
nationality2id?: number;
subscriptiondate?: Date;
recorddate?: Date;
defaultlanguage:String;
billcategory: String;
comment?: String;
}
编辑2: member-details.component.html:
<mat-card class="example-card">
<mat-card-header>
<div mat-card-avatar>
<i class="material-icons md-36">
face
</i>
</div>
<mat-card-title>Persönliche Daten</mat-card-title>
<mat-card-subtitle>Stammdaten des Mitglieds</mat-card-subtitle>
<div>
<i class="material-icons">
edit
</i>
<i class="material-icons">
save
</i>
</div>
</mat-card-header>
<mat-card-content>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Vorname" required [(ngModel)]="memberDetailsData.member.firstname" name="firstname">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Nachname" value="{{memberDetailsData.member.surname}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="true" matInput placeholder="MitgliedsNr." value="{{memberDetailsData.member.memberid}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Mitgliedsart" value="{{memberDetailsData.member.membertype}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Hauptmitglied" value="{{memberDetailsData.member.mainmemberid}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Geburtsdatum" value="{{memberDetailsData.member.birthdate | date}}">
</mat-form-field>
<!--mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Nationalität 1" value="{{mapCountry(memberDetailsData.member.nationality1id).country}}">
</mat-form-field-->
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Nationalität 1" value="{{memberDetailsData.member.nationality1id}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Nationalität 2" value="{{memberDetailsData.member.nationality2id}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Anmeldedatum" value="{{memberDetailsData.member.subscriptiondate | date}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Erfassungsdatum" value="{{memberDetailsData.member.recorddate | date}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Bevorzugte Sprache" value="{{memberDetailsData.member.defaultlanguage}}">
</mat-form-field>
<mat-form-field>
<input [disabled]="inputsMemberDisabled" matInput placeholder="Rechnungskategorie" value="{{memberDetailsData.member.billcategory}}">
</mat-form-field>
<mat-form-field class="example-full-width">
<textarea [disabled]="inputsMemberDisabled" matInput placeholder="Kommentar" value="{{memberDetailsData.member.comment}}"></textarea>
</mat-form-field>
</mat-card-content>
<mat-card-actions>
<button mat-raised-button color="primary" [disabled]="!inputsMemberDisabled" (click)="toggleDisabledInputs()">Bearbeiten</button>
<button mat-button mat-raised-button color="warn" [disabled]="inputsMemberDisabled" (click)="updateMemberInformation()">Speichern</button>
</mat-card-actions>
</mat-card>
- 在
global-data-service
服务的getCountryList()
函数中,您正在 returning 一个Country
的普通数组,但它是从 Observable 内部检索的。 return 服务中的可观察值也会更好地为您服务。这样,我们可以确保member-details
组件中的this.countryList
变量被分配了正确的值。
全局数据-service.ts
getCountryList(): Observable<Country[]> {
const result = Subject<Country[]>();
if (this.countryList.length < 1) {
this.initializeCountryList().subscribe(
res => {
this.countryList = res;
result.next(res);
}
);
}
return result.asObservable();
}
成员-details.component.ts
ngOnInit() {
this.inputsMemberDisabled = true;
this.memberid = this.route.snapshot.params['id'];
this.globalDataService.getCountryList().subscribe(countries => { this.countryList = countries });
this.getMemberDetails();
}
- 在 HTML 模板中,使用 optional chaining operator (
?.
) 以确保在访问变量的属性之前先定义该变量。因此,将memberDetailsData.member
的所有实例替换为memberDetailsData?.member
。这相当于在访问它的属性之前检查memberDetailsData
是否被定义。如果您需要检查子属性是否存在,您可以继续memberDetailsData?.member?.firstname
.
您可以在打印数据的模板部分使用 *ngIf
指令来检查数据是否已设置。如果设置它将显示数据,否则该块将不会在 DOM 中呈现。喜欢
<div *ngIf = "memberDetailsData">
<!-- Template part goes here -->
</div>
或者您可以在访问对象的成员时使用三元运算。
memberDetailsData?.member
同时将值分配给输入字段。
希望能解决您的问题