我有一个要根据用户输入的字段进行过滤的表,并且该表的源是由BehaviorSubject制成的可观察对象。设置如下:
class Component {
//filled with a http call to a webservice
private subject$ = new BehaviorSubject([])
public state = 'Open';
public workOrders$ = this.subjects$.asObservable().pipe(map(orders => {
return orders.filter(f => f.State == this.state)
}));
}
,重复的tr的HTML是
<tr *ngFor="let order of workOrders$ | async">
以及状态输入字段的HTML
<input type="text" [(ngModel)]="state" />
在初始加载时,这可以按状态正确过滤所有工作订单,但是每当this.state
发生变化时,我都希望该管道重新过滤数组以更新表。完成此类任务的最佳实践是什么?我不想突变主题,因为当过滤器再次更改时,我需要保留原始数据集。
答案 0 :(得分:0)
您可以使用rxjs combineLatest函数,并且可以观察到需要重新计算的情况:
private subject$ = new BehaviorSubject([])
public state = 'Open';
public stateSubject = new BehaviorSubject(this.state);
public workOrders$ = combineLatest(
this.subjects$,
this.stateSubject,
(orders, state) => {
return orders.filter(f => f.State == state)
}
);
然后在您的输入上:
<input type="text" (ngModelChange)="stateSubject.next($event)" [(ngModel)]="state" />
答案 1 :(得分:0)
您提到state
来自一个输入字段,这意味着(假设FormsModule
是导入的,应该考虑ngModel
),我们可以将该值作为Observable获得。
您可以使用switchMap
订阅一个Observable,将其发射映射到另一个Observable,并让结果Observable从第二Observable发出值,直到第一个Observable再次发出(您 switch 到新的Observable)。
根据表单的设置方式,甚至是使用(keyup)
绑定,您可以通过多种不同的方式从表单控件中获取“值的可观察值”。没有
ngForm
在附加到控件的模板中声明,您只需通过模板绑定查询ngModel
:
<input type="text" [(ngModel)]="state" #value="ngModel"/>
然后在您的组件中
类组件{
@ViewChild('value') value: NgModel;
//filled with a http call to a webservice
private subject = new BehaviorSubject([])
public state = 'Open'; // This remains as a component property, but we don't need it for the Observable stream as we'll get the value changes Observable from the form control.
public workOrders = this.subject.asObservable().pipe(
switchMap(this.value.valueChanges),
withLatestFrom(this.subject),
map([inputValue, orders] => {
return orders.filter(f => f.State === inputValue.value)
}));
}
您还可以从http调用和输入值更改中分别管理预订,但这很无聊。
如您所见,以上内容有些复杂;我们需要withLatestFrom
来保留http调用的值,我假设该值一经收到即为静态。由于您使用的是标记中的async
管道来订阅和调用Observable,因此最好只过滤另一个管道的结果,这可能是一个更好的设计选择!
@Pipe({name: 'filterState'})
export class FilterStatePipe implements PipeTransform {
transform(value: YourTypeHere[], state: string) {
return value.filter(s => s.State === state);
}
}
然后在模块中声明它,并在标记中使用它,如下所示:
<input type="text" [(ngModel)]="state" />
<tr *ngFor="let order of workOrders$ | async | filterState:state">
async
为您解包了Observable,然后您的自定义管道将根据state
的值过滤该值。 state
更改后,应重新运行管道。
答案 2 :(得分:0)
您需要订阅输入值的更改 可以通过将表单(假设输入字段在表单内)转换为反应形式,或在输入值发生变化时调用函数来完成此操作。 有关反应式的更多信息,请参见here 我将介绍第二种最简单的方法: HTML
<input type="text" (ngModelChange)="dataChanged()" [(ngModel)]="state" />
TS
class Component {
//filled with a http call to a webservice
private subject$ = new BehaviorSubject([])
public state = 'Open';
public allorders
//Variable to hold all the subjects before applying any filter
this.subjects$.asObservable().subscribe( val => {
this.allorders = val
})
}
dataChanged(){
this.allorders.filter(f => f.State == this.state)
}));
}