根据从不同组件(同级)的多重选择中选择的值过滤显示的数据

时间:2019-01-27 16:48:57

标签: angular

我有两个组成部分。一个由多选下拉列表组成。另一个显示通过服务从api获取的数据。

我想根据多重选择中选择的值来过滤显示的数据。该如何处理?

stackblitz 在这次堆叠闪电战中,我复制了该结构。 select组件包含multiselect,hello组件显示通过api.service从api获取的数据。在multiselect中选择的值通过另一个过滤器(即filter.service)发送到hello组件。我可以显示所选的值,但我想根据这些值过滤数据。

P.S:在堆栈闪电战中,我明确提到了app.component中两个组件的选择器。但是在我的项目中,组件是通过路由器插座提供的。

1 个答案:

答案 0 :(得分:1)

Angular IO Guides(进入基本链接)是解决此类问题的基本知识的好地方。 This section解释了一些组件交互。

在您的情况下,您的两个组件可能是调用您的服务的组件的子组件。该包装器可能会向显示组件提供从API结果复制的列表(或流),并且可能正在侦听下拉组件的输出。当输出触发时,包装器可以修改发送到显示组件的复制列表(或流)。

这是一个粗糙的示例,但作为免责声明,这是理论上的,我没有运行它。

// wrapper html

<multiselect-component (selectionChange)="selectedItems($event)"></multiselect-component>
<display-component [items]="displayItems$ | async"></display-component>


//wrapper ts

private selectedSubject = new BehaviorSubject<any>(); // add your type
set selectedItems(items: any[]) { // add your type
    this.selectedSubject.next(items);
}

displayItems$: Observable<any>; // add your own type

ngOnInit() {
    // the static 'merge' from 'rxjs' to allow both streams to trigger
    this.displayItems$ = merge(
        this.apiService.getData(), // should return an observable
        this.selectedSubject.asObservable(),
    ).pipe(
        // something similar to this
        switchMap((data, filterItems) =>
            data.filter(d =>
                !filterItems.includes(d)
            )
        ),
    );
}

我还将提供免责声明Angular是一个非常自以为是的框架。做事有很多方法!另外,RXJS可以为您做很多事情。这时最简单的方法是做与以前几乎相同的事情。


添加StackBlitz之后:

this.changeDetectorRef.detectChanges();内不需要

init。我也认为您根本不必自己检测更改。我发现,如果必须这样做,通常 (但并非总是如此)意味着计划/结构中有些许问题。还有多种解决方法,我个人坚持使用容器(页面)组件和显示组件。

类似

//display component
ngOnInit() {
    // the static 'merge' from 'rxjs' to allow both streams to trigger
    this.obs = merge(
        this.cardsInfo.getCardsInfo(), // should return an observable
        this.filterService.getCategories(),
    ).pipe(
        // something similar to this
        switchMap((data, filterItems) =>
            data.filter(d =>
                !filterItems.includes(d)
            )
        ),
    );
}

在我看来,您似乎也正在尝试遵循this StackBlitz中的this Angular Material example (go to table with filtering)