由于标题肯定不会进一步促进我的意图,这就是我想要做的事情。
我想在视图中显示一个项目列表,我从后端异步获取(我有一个名为fetchItems()
的方法的服务来获取具有Observable<Item[]>
返回类型的方法。
我通过设置this.items = this.itemService.fetchItems();
在组件构造函数中初始化此列表
我通过*ngFor="let item of items | async"
显示视图中的项目列表。
到目前为止,这么好,一切都按预期工作。
每个项目都有一个字段subItemId
。我想使用此键在上述列表中显示类型为SubItem
的实际子项对象。我可以通过this.subItemService.findById(subItemId)
获取此项目,该项目会返回Observable<SubItem>
。
我该怎么做呢?
我显然不能从模板中调用getSubItem(item: Item): SubItem
这样的组件方法,因为它会被反复调用。
我不想修改itemService.fetchItem()
方法以急切加载子项,因为它们可能在任何使用它的地方都不需要。
答案可能很明显,但我只与Angular(6)合作了几天。
答案 0 :(得分:1)
您在模板中使用了async
,这意味着模板的数据绑定是延迟加载的。因此,除了对子项目再次使用async
之外,您无法做任何事情。
<div *ngFor="let item of items | async">
<span>{{(getSubItem(item: Item) | async)?.title}}</span>
</div>
上面会调用一个返回observable的函数,?
表示在读取title
属性之前结果是可选的。
你可以看到这里的限制是什么。如果您需要多个属性,则必须执行另一个async
操作。这不太实际。
您需要加载模板的所有数据或更改API后端以在单个API调用中获取所有数据。
你最终会需要这样的东西。
this.itemService.fetchItems().first().subscribe((items)=>{
this.items = items;
this.items.forEach((item)=>{
this.getSubItem(item).first().subscribe((sub)=> {
// attach the child to the parent item
item.child = sub;
});
});
});
然后,您可以在模板中迭代items
,并使用item.child
作为该父项的子项。您需要使用?
运算符,因为数据是延迟加载的,并且在第一次呈现项目时不会存在。
答案 1 :(得分:1)
您可以重建项目的父子关系&gt; subitem使用rxjs运算符。这是一个example:
export class AppComponent {
name = 'Angular 6';
itemsWithSubItems: Observable<any>;
subItems: Observable<any[]>;
getItems(): Observable<{ subItemId: number, itemName: string, subItem?: any }[]> {
return of([{ subItemId: 1, itemName: 'One'}, { subItemId: 2, itemName: 'Two' }, { subItemId: 3, itemName: 'Three' }, { subItemId: 4, itemName: 'Four' }])
.pipe(shareReplay());
}
constructor() {
this.itemsWithSubItems = this.getItems().pipe(
flatMap(items => from(items)),
switchMap(item => this.getSubItemById(item.subItemId),
(outerValue, innerValue, outerIndex, innerIndex) => {
outerValue.subItem = innerValue;
return outerValue
}),
toArray());
this.itemsWithSubItems.subscribe(x => console.log('x', x))
}
getSubItemById(subItemId: number): Observable<{name: string}> {
return of({ name: `${subItemId}-SubItem` });
}
}