来自2个不同Web服务的Angular Populate mat-optgroup / mat-options
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了来自2个不同Web服务的Angular Populate mat-optgroup / mat-options相关的知识,希望对你有一定的参考价值。
我是Angular的新手,并尝试在我的Angualr 6应用程序中添加带选项组的mat-select。我有一个包含2个URL的现有Web API。一个URL返回Groups,另一个返回给定groupId的每个Group中的Items。
加载时,此页面进入无限循环。为了排除故障,我尝试在ngOnInit()中为this.groups添加一个记录器,这样我就可以构造html使用的数组,但看起来像.groups / this.items没有初始化,直到HTML页面调用。
我必须接近这个错误。我只是尝试添加一个HTML mat-select,其中mat-optgroups由1 webservice确定/ mat-options由另一个webservice确定。
我基于这个例子(https://material.angular.io/components/select/overview#creating-groups-of-options)构建了这个:
navigation.component.ts
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import {HttpErrorResponse} from '@angular/common/http';
import {Component, OnInit} from '@angular/core';
import { Group } from '../group';
import { GroupService } from '../group.service';
import { Item } from '../item';
import { ItemService } from '../item.service';
@Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.css']
})
export class NavigationComponent implements OnInit {
groups: Group [] = [];
items: Item [] = [];
pokemonControl = new FormControl();
constructor(private groupService: GroupService, private itemService: ItemService) {}
ngOnInit () {
this.getGroups();
console.log("length: " + this.groups.length); // logs 0 as length
}
getGroups(): void {
this.groupService.getGroups().subscribe(
data => {
this.groups = data as Group[];
console.log(data);
},
(err: HttpErrorResponse) => {
console.log (err.message);
}
);
}
getItems(department: number): void {
this.itemService.getItems(department).subscribe(
data => {
this.items = data as Item[];
console.log(data);
},
(err: HttpErrorResponse) => {
console.log (err.message);
}
);
}
}
group.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
import { Group } from './group';
@Injectable({
providedIn: 'root'
})
export class GroupService {
private groupsUrl = 'http://localhost:8180';
constructor(private http: HttpClient) { }
getGroups (): Observable<Group[]> {
const url = `${this.groupsUrl}/groups`;
return this.http.get<Group[]>(url);
}
private handleError<T> (operation = 'operation', result?: T) {
return (error: any): Observable<T> => {
console.error(error);
console.log(`${operation} failed: ${error.message}`);
return of(result as T);
};
}
}
item.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
import { Item } from './item';
@Injectable({
providedIn: 'root'
})
export class ItemService {
private itemsUrl = 'http://localhost:8180';
constructor(
private http: HttpClient) { }
getItems (groupId: number): Observable<Item[]> {
const url = `${this.itemsUrl}/groups/${groupId}/items`;
return this.http.get<Item[]>(url);
}
private handleError<T> (operation = 'operation', result?: T) {
return (error: any): Observable<T> => {
console.error(error);
console.log(`${operation} failed: ${error.message}`);
return of(result as T);
};
}
}
HTML
<mat-select [formControl]="pokemonControl">
<mat-optgroup *ngFor="let group of group.groupList" [label]="group.groupName"
[disabled]="group.disabled">
<mat-option *ngFor="let item of getItems(group.groupId).itemList" [value]="item.itemId">
{{item.itemName}}
</mat-option>
</mat-optgroup>
</mat-select>
检查这一行:
let item of getItems(group.groupId).itemList
这条指令在另一个*ngFor
中,所以它执行的时间与group.groupList
的长度一样多。
如果它是10个元素长,getItems(...)
方法将被调用10次,并且每次它将产生HTTPRequest,并且在异步应答之后,它将覆盖items
变量。
因此行为是不可预测的,并且items
变量不可用,因为它在几秒钟内改变了几次。你说的体验就像一个无限循环,它可能只是变化检测,它响应新的变化产生一个新的变化。
Solution:
如果您需要同步使用它们,请不要订阅多个observable!
Observable是异步的。您无法猜测它何时会执行订阅代码,即订单或时间。
Rxjs为几个运营商提供了解决这个问题的方法。你可以检查合并运营商here。
以上是关于来自2个不同Web服务的Angular Populate mat-optgroup / mat-options的主要内容,如果未能解决你的问题,请参考以下文章
具有来自 Web 服务的动态元数据的 Angular 6 元服务