我有根据特定日期从服务器中提取的数据。因此,当日期更改时,我再次从服务器查询以获取新数据。我还具有从服务器手动触发刷新的功能(用于从中提取数据的情况,因此我需要重新拉动)
private _date = new BehaviorSubject(new Date())
private _refresh = new BehaviorSubject<void>(undefined);
readonly data$: Observable<Model[]> = combineLatest([this._date, this._refresh])
.pipe(
switchMap(([date, refresh]) => this.dataService.get(date)),
shareReplay(1)
)
我的视图正在使用异步管道显示data$
我需要能够操纵data$
中的列表,以便跟踪列表中的已修改项。
Model {
...
isModified: boolean
}
我的模型是这样的,所以如果我对元素进行更改,我希望能够将其推入数据列表(删除旧项目->替换为新的修改项目),然后发出data$
更新列表。
然后,如果_date
发出$data
会发出该消息,并且所有修改的内容都会被清除。
我试图不直接更改列表中的项目,以便可以利用ChangeDetectionStrategy.OnPush
有没有一种方法可以组合手动更新列表和_date
更新列表的过程,但是当从服务器中提取优先级时。
仅维护一个列表应该可以让我更轻松地基于数据获取汇总。随着项目的更新,我的合计值将根据修改后的列表进行更新。如果我要维护第二个已修改项列表,则如果我想要处于已修改状态的汇总值,则需要对两个列表进行比较(获取未修改的主列表中的所有项以及已修改列表中的所有项)。>
批处理更新应该和
一样简单data$.pipe(
filter(x => x.isModified),
switchMap(x => dataService.update(x))
)
这是一个stackblitz,我相信它将有助于证明这一点。
在这里您可以看到我有一个组件,可用于更新从我的观察站返回的物品的名称。我希望能够修改这些项目,然后将它们存储回可观察对象中。这样,如果我想获取所有修改的项目,我可以在该可观察项上应用过滤器以获取修改的项目。同样,如果您更改了可观察到的日期将从服务器重新启动,并且已删除项目的列表也将被清除。
请参见DataService.itemNameChanged
答案 0 :(得分:1)
要解决此问题,您可以使用扫描运算符在数组中保存新项目的值。
在这里创建了BehaviorSubject,以发出每个修改后的新项目的值,并使用默认数组的第一个值对其进行初始化。
private itemModified = new BehaviorSubject<Model>(data[0]);
每次更新dateRefresh $的基本可观察值时,都应重置此值。
readonly dateRefreshHttp$: Observable<Model[]> = combineLatest([
this._date,
this._refresh
]).pipe(
tap(() => this.itemModified.next(data[0])),
switchMap(([date, refresh]) =>
将扫描运算符添加到switchMap内,以便在更改累加时重新启动累加。请注意,添加的反跳运算符允许在不失去焦点的情况下多次输入字符。
switchMap(([date, refresh]) =>
combineLatest([from([data]), this.itemModified]).pipe(
scan(
(acc: any[], [data, itemModified], index: number) => {
return acc.map(item =>
item.id == itemModified.id ? itemModified : item
);
},
[...data]
)
)
),
debounceTime(300)
);
最后,通过itemNameChanged函数发出一个新值。
itemNameChanged(newName: string, item: Model) {
const newItem: Model = {
id: item.id,
name: newName,
isModified: true
};
this.itemModified.next(newItem);
}
实时示例Stackblitz