如何从子组件中过滤父组件中的可观察对象?

How to filter observable in parent component from child component?

我有两个组件。

  1. 项目列表 -- 用于显示项目列表(父级)
  2. 项目 -- 单个项目(子项)的包装器

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>