如何从子组件中过滤父组件中的observable?

时间:2018-05-27 21:44:54

标签: angular rxjs observable angular6

我有两个组成部分。

  1. 项目列表 - 用于显示项目列表(父项)
  2. 项目 - 单个项目(儿童)的包装
  3. Item List component我基本上使用服务创建一个observable。函数getItems()返回一个可观察的项目:

    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);
    }
    

    此操作需要一些时间,因此我想从父组件中的observable中“本地”删除它。

    我可能必须过滤父组件中的observable并以某种方式返回一个新的过滤的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
    }
    

    正如您在上面所看到的,我不知道如何“连接”到observable并过滤它。

    原因是当我想要为删除操作设置动画(如淡出)时,项目会闪烁。这是因为动画的结束时间早于从火库中删除的记录。

1 个答案:

答案 0 :(得分:1)

我建议你把你的卡片作为Presentation / Dumb组件。意味着您应该从中删除服务依赖项,因为它的主要工作是显示项目。

然后,一个简单的解决方案是将一个输出添加到发出删除事件的卡片项目中,告诉其父组件“嘿!你应该删除我”。

所以,基本上在 card-item.component.ts 中,您的代码如下所示:

@Input() item: Item;
@Output() removeClick = new EventEmitter<Item>();

removeItem() {
    this.removeClick.emit(this.item);
}

现在,我们来自可观察部分的“移除”。我更喜欢使用术语过滤器,因为可观察量是流,您只是在某个时间点观察值。相反,您可以从项目数组中删除项目。 在这种情况下,您需要保留当前显示的项目的本地副本。意味着删除异步管道并在组件代码中订阅您的o​​bservable。

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>