我有一个Angular应用,其中的mat-table
非常大。该表的大多数单元都是mat-select
组件(来自Angular Material),并且当mat-select
中的值更改时,需要保存该值,但要遵循以下规则:
我的攻击计划是这样的:
selectionChange
中的任何mat-select
上,将整个数据对象发射到Subject
上。Subject
,并通过以下管道运行它:
combineLatest
组合了两个Observable,interval(7000)
和Subject
要保存的数据,并对其进行过滤以仅获取完整的数据。并只取其中一个发出的最后一个。这是我所做的(简化):
<mat-table>
<ng-container matColumnDef='someData'>
<mat-header-cell *matHeaderCellDef>Some Data</mat-header-cell>
<mat-cell *matCellDef='let row'>
<mat-form-field>
<mat-select [(ngModel)]='row.someData' (selectionChange)='dataToSave.next(row)'>
<mat-option [value]='3'>High</mat-option>
<mat-option [value]='2'>Medium</mat-option>
<mat-option [value]='1'>Low</mat-option>
</mat-select>
</mat-form-field>
</mat-cell>
</ng-container>
...
</mat-table>
import { Component, OnInit, AfterViewInit, OnDestroy } from '@angular/core';
import { DataService } from '../service/data.service';
import { Subject } from 'rxjs/Subject';
import { filter, switchMap, buffer, startWith } from 'rxjs/operators';
import { interval } from 'rxjs/observable/interval';
import { combineLatest } from 'rxjs/observable/combineLatest';
@Component({
selector: 'app-data-grid',
templateUrl: './data-grid.component.html',
styleUrls: ['./data-grid.component.scss']
})
export class DataGridComponent implements OnInit, AfterViewInit, OnDestroy {
dataToSave = new Subject<any>();
// trigger the buffer either when 7 seconds has passed, or a row has been completed.
bufferCondition = combineLatest(
interval(7000).pipe(
startWith(0)
),
this.dataToSave.pipe(
startWith({}),
filter(row => this.checkAllFieldsCompleted(row))
)
);
constructor(private dataService: DataService) { }
ngAfterViewInit() {
this.dataToSave.pipe(
buffer(this.bufferCondition),
filter(dataArray => data && dataArray.length > 0),
switchMap(dataArray => this.dataService.saveData(dataArray))
).subscribe(dataSaved => {
/* success */
}, err => {
/* error */
});
}
checkAllFieldsCompleted(row: any): boolean {
return /* logic to check if complete */
}
...
}
我认为这将是反应式扩展的完美使用!但我似乎不太能使它正常工作。如果仅使用bufferTime
运算符,则一切正常。因此,我认为错误在于我如何定义自定义缓冲区条件。
答案 0 :(得分:0)
经过一番挖掘和反复试验后,我有了解决方案。
我从this website中学到了
请注意,
combineLatest
在每个可观察对象发出至少一个值之前不会发出初始值。
在我的缓冲条件下,我试图将两个可观察值组合在一起:7秒间隔和一行完成的时间。我注意到预期的行为只是在我第一次完成一行之后 开始-直到那时它才会每7秒开始保存一次。问题是filter
上的dataToSave
运算符可观察到。 combineLatest
不会发出任何东西,直到两个观察物都发出了东西。
我更改了此代码:
bufferCondition = combineLatest(
interval(7000).pipe(
startWith(0)
),
this.dataToSave.pipe(
startWith({}),
filter(row => this.checkAllFieldsCompleted(row))
)
);
对此:
bufferCondition = combineLatest(
interval(7000),
this.dataToSave.pipe(
filter((row, index) => index === 0 || this.checkAllFieldsCompleted(row))
)
);
,效果很好!基本上,我不需要startWith
运算符,并且在filter
上,我具有可观察到的对数据的第一个更改,但在行完成之前没有其他更改。