如何从子组件中过滤父组件中的可观察对象?
How to filter observable in parent component from child component?
我有两个组件。
- 项目列表 -- 用于显示项目列表(父级)
- 项目 -- 单个项目(子项)的包装器
在 Item List component
中,我基本上使用服务创建了一个可观察对象。函数 getItems() return 是一个可观察的项目:
items$: Observable<Item[]>;
ngOnInit() {
this.items$ = this.service.getItems();
}
在模板中,我使用异步管道执行 ngFor 以显示项目列表:
<div *ngFor="let item of items$ | async">
<card-item [item]="item"></card-item>
</div>
现在,在 Item component
中,我可以选择从 firestore 数据库中删除该特定项目:
@Input() item: Item;
removeItem() {
this.service.removeItem(this.item.id);
}
此操作需要一些时间,因此我想将其从父组件的可观察对象中删除"locally"。
我可能必须在父组件中过滤 observable 并以某种方式 return 一个新的过滤 observable,但我不知道如何从子组件管理它?
removeItem() {
// remove from firestore, but this can take some time
this.service.removeItem(this.item.id);
// meanwhile... remove it from the observable on parent
source.pipe(filter(item => item.id !== this.item.id)); // here is the problem I have
}
正如您在上面看到的,我不知道如何 "connect" 到可观察对象并对其进行过滤。
原因是当我想为删除操作设置动画(如淡出)时,该项目会闪烁。这是因为动画完成的时间早于从 firestore 中删除记录的时间。
我建议您将卡片项目保留为 Presentation/Dumb 组件。意味着您应该从中删除服务依赖性,因为它的主要工作是显示项目。
然后,一个简单的解决方案是向卡片项目添加一个输出,该项目发出移除事件,告诉其父组件 "hey! you should delete me"。
因此,基本上在 card-item.component.ts 中,您的代码如下所示:
@Input() item: Item;
@Output() removeClick = new EventEmitter<Item>();
removeItem() {
this.removeClick.emit(this.item);
}
现在,我们从可观察的部分来到"remove"。我更喜欢使用术语 filter 因为可观察对象是流,你只是在某个时间点观察值。相反,您可以从项目数组中删除项目。
在这种情况下,您需要保留当前显示项目的本地副本。意味着删除异步管道并在您的组件代码中订阅您的可观察对象。
并且在您的 item-list.component.ts
ngOnInit() {
this.items$ = this.service.getItems();
this.items$.subscribe(items => {
this.localItems = items;
}
)
}
onRemoveClick($event: Item) {
// Removal logic here
// Something like
const index = this.localItems.indexOf($event);
if (index > -1) {
this.localItems.splice(index, 1);
}
}
在你的item-list.component.html中:
<div *ngFor="let item of localItems">
<card-item [item]="item" (removeClick)="onRemoveClick($event)"> </card-item>
</div>
我有两个组件。
- 项目列表 -- 用于显示项目列表(父级)
- 项目 -- 单个项目(子项)的包装器
在 Item List component
中,我基本上使用服务创建了一个可观察对象。函数 getItems() return 是一个可观察的项目:
items$: Observable<Item[]>;
ngOnInit() {
this.items$ = this.service.getItems();
}
在模板中,我使用异步管道执行 ngFor 以显示项目列表:
<div *ngFor="let item of items$ | async">
<card-item [item]="item"></card-item>
</div>
现在,在 Item component
中,我可以选择从 firestore 数据库中删除该特定项目:
@Input() item: Item;
removeItem() {
this.service.removeItem(this.item.id);
}
此操作需要一些时间,因此我想将其从父组件的可观察对象中删除"locally"。
我可能必须在父组件中过滤 observable 并以某种方式 return 一个新的过滤 observable,但我不知道如何从子组件管理它?
removeItem() {
// remove from firestore, but this can take some time
this.service.removeItem(this.item.id);
// meanwhile... remove it from the observable on parent
source.pipe(filter(item => item.id !== this.item.id)); // here is the problem I have
}
正如您在上面看到的,我不知道如何 "connect" 到可观察对象并对其进行过滤。
原因是当我想为删除操作设置动画(如淡出)时,该项目会闪烁。这是因为动画完成的时间早于从 firestore 中删除记录的时间。
我建议您将卡片项目保留为 Presentation/Dumb 组件。意味着您应该从中删除服务依赖性,因为它的主要工作是显示项目。
然后,一个简单的解决方案是向卡片项目添加一个输出,该项目发出移除事件,告诉其父组件 "hey! you should delete me"。
因此,基本上在 card-item.component.ts 中,您的代码如下所示:
@Input() item: Item;
@Output() removeClick = new EventEmitter<Item>();
removeItem() {
this.removeClick.emit(this.item);
}
现在,我们从可观察的部分来到"remove"。我更喜欢使用术语 filter 因为可观察对象是流,你只是在某个时间点观察值。相反,您可以从项目数组中删除项目。 在这种情况下,您需要保留当前显示项目的本地副本。意味着删除异步管道并在您的组件代码中订阅您的可观察对象。
并且在您的 item-list.component.ts
ngOnInit() {
this.items$ = this.service.getItems();
this.items$.subscribe(items => {
this.localItems = items;
}
)
}
onRemoveClick($event: Item) {
// Removal logic here
// Something like
const index = this.localItems.indexOf($event);
if (index > -1) {
this.localItems.splice(index, 1);
}
}
在你的item-list.component.html中:
<div *ngFor="let item of localItems">
<card-item [item]="item" (removeClick)="onRemoveClick($event)"> </card-item>
</div>