异步管道的Angular 9过滤器结果



我对angular有点陌生,我正在做一个应用程序来更好地学习。我有一个关于绑定和过滤http调用结果的问题。在下面的代码中,我试图绑定一些数据的列表。

在服务中,我接到这样的电话

getTestFields(): Observable<Engagement[]> {
return this.httpClient.get<Engagement[]>(this.url + '/testFields');
}

它基本上返回一些测试字段的列表;在component.ts,我将调用结果绑定到一个可观察变量。

dataSet$: Observable<Engagement[]>;
ngOnInit(): void {
this.dataSet$ = this.service.getTestFields();
}

在html模板中,我将数据绑定如下:

<table class="table table-hover" *ngIf="dataSet$ | async as resultSet; else loading">
<tr *ngFor="let item of resultSet" >
<td>{{item.testName}}</td>
<td>{{item.planned}}</td>
<td>{{item.workingOn}}</td>
<td>{{item.reviewed}}</td>
</tr>   </table>

在这里之前我没有问题;我成功地获得了数据并显示在表中。问题在于过滤;我不知道如何过滤我已经从服务器上得到的数据。我不想进行服务器调用来过滤数据,我想过滤我已经得到的当前列表。

我试过下面这样的东西,但没用。

filter() {
this.dataSet$ = this.dataSet$.pipe(
switchMap(data => {
return data.filter(p => p.planned)
})
);
}

如何在不向服务器发送新调用的情况下筛选现有的可观察列表?

尝试与数组filter耦合的rxjsmap运算符。

Map转换可观察到的,因此在本例中,我们使用它来转换数组,使其仅包括planned为true的项。

import { map } from 'rxjs/operators';
.....
ngOnInit(): void {
this.dataSet$ = this.service.getTestFields().pipe(
map(data => data.filter(p => p.planned)),
);
}

您也可以使用rxjsfilter操作符从Observable中filter发射,但我认为在这种情况下不需要它。

====================RxJS筛选器的使用================

import { filter } from 'rxjs/operators';
...
ngOnInit(): void {
this.dataSet$ = this.service.getTestFields().pipe(
// make sure data is truthy and has a length before emitting to 
// the consumer (in this case it is the HTML).
filter(data => !!data && !!data.length),
);
}

我同意AliF50,只是稍作调整,因为我假设你有一个过滤器按钮,或者你想在加载数据后过滤掉。

dataSet$: Observable<Engagement[]>;
ngOnInit(): void {
filter();
}
filter() {
this.dataSet$ = this.service.getTestFields().pipe(
map(data => data.filter(p => p.planned)),
);
);
}

还有一种情况是,一旦加载数据,就永远不想去服务器,然后可能需要在组件级别进行订阅。

dataSet: Engagement[];
ngOnInit(): void {
this.dataSet = this.service.getTestFields().subscribe(response => this.dataSet = 
response);
}
filter() {
this.dataSet = this.dataSet.filter(data => data.planned === true)
}

我遇到了一个混合解决方案;把责任分开是解决我问题的关键;我在async管道中实现了一个自动完成,该管道指向它自己的列表,但我无法正确处理过滤器,所以我们开始:

我亲爱的自动完成组件.ts


import {
ChangeDetectionStrategy,
Component,
OnInit,
Input,
Output, EventEmitter
} from '@angular/core';
import { FormControl } from '@angular/forms';
import { MyInterface } from '~interfaces-whatsoever';
import { map, startWith } from 'rxjs/operators';
import { Observable } from 'rxjs';

@Component({...})
export class MyDearAutocompleteComponent
implements OnInit
{
@Input() controlName: string;
@Input() control: FormControl;
@Input() options: MyInterface[];
@Output() selectOptionEvent = new EventEmitter<MyInterface>();
filteredOptions: Observable<MyInterface[]>;
ngOnInit() {
this.filteredOptions = this.control.valueChanges.pipe(startWith(''), map(name => this.isOptionNameMatch(name)));
}
isOptionNameMatch(value: string): MyInterface[] {
const clause = (option: MyInterface) => { do your stuff test here };
return (typeof value === 'string') ? this.options.filter(clause) : this.options;
}
selectOption(value: MyInterface) {
this.selectOptionEvent.emit(value);
}
}

其中@Input() options: MyInterface[];是组件父级使用以下内容给出的完整列表:

options$ | async as options; else loading
...
<app-my-dear-autocomplete ... [options]="options" ... ></app-my-dear-autocomplete>

我亲爱的autocomplete.component.html

<mat-form-field appearance="fill" fxFlex="100">
<mat-label>My dear option list</mat-label>
<input type="text" required matInput [matAutocomplete]="optionAutocomplete" [formControl]="control"/>
<mat-autocomplete #optionAutocomplete="matAutocomplete" (optionSelected)="selectOption($event.option.value)">
<mat-option *ngFor="let option of filteredOptions | async" [value]="option">
{{ option.whatsoever }}
</mat-option>
</mat-autocomplete>
</mat-form-field>

这样做并像订阅it输出的组件一样使用自动完成帮助我与其他组件一起处理选择事件。

希望它能有所帮助,我当然愿意接受的建议

最新更新