我有一个秋田商店,里面装满了来自服务器的数据。我正在尝试从商店获取一个对象并使用角度双向绑定 [()] 对其进行编辑。
每当我尝试更改对象的值时(在模板 HTML 中通过键入字段或在从服务加载数据后在组件 Typescript 中)我都会收到有关该属性不可编辑的错误。
我尝试在 Akita EntityStore 中添加 ImmerJS 并尝试在组件中使用 {...data} 。结果相同。
一些代码...
秋田店:
export interface GradingMetaState extends EntityState<Grading, number>, ActiveState {
loading: boolean;
gradings: Grading[];
}
@StoreConfig({ name: 'gradingMetaStore', producerFn: produce})
export class GradingMetaStore extends EntityStore<GradingMetaState> {
constructor() {
super();
}
}
来自服务的位,这是向组件返回数据:
public get gradings$(): Observable<Grading[]> {
return this.gradingMetaQueries.selectAll();
}
从组件:
ngOnInit(): void {
this.gradings = new Array<Grading>();
this.busy = true;
this.service.gradings$.subscribe((gradings) => {
// this.gradings = {...gradings}; - error about can only be array/iterable
this.gradings = gradings;
if (this.gradings.length > 0) {
// Data is present, but this code produces error in browser console
// "ERROR TypeError: "firstName" is read-only"
this.log.debug('changing Albert Einstein to william Einstein');
this.gradings[1].examiners[1].firstName = 'william'; // ERR line
this.log.debug('changing Albert Einstein to william Einstein DONE');
}
this.busy = false;
});
}
上面的组件如上所述错误,但是如果我从那里删除名称设置,如果我尝试编辑输入字段中的值,我会得到相同的结果:
<mat-form-field>
<mat-label>First name</mat-label>
<input matInput [disabled]="busy" (blur)="saveGrading(grading)"
[(ngModel)]="examiner.firstName" placeholder="First name">
</mat-form-field>
该值在模板加载时填充在页面上。
现在很可能我错过了 Angular 和/或 Akita 的一些关键方面,请随时告诉我!
编辑 - 潜在的解决方案 所以商店里的 Immer 似乎没有做我希望返回“草稿”对象的事情,我认为这是可变的(https://datorama.github.io/akita/docs/immer/)。
在我的服务中,我有代码通过查询从商店获取数据。我尝试更改服务(下面添加的代码很糟糕,承认)以复制数据存储对象并返回副本。这似乎允许端到端功能发挥作用。
但是我不确定这是正确的做法......
旧服务方式:
public get gradings$(): Observable<Grading[]> {
return this.gradingMetaQueries.selectAll();
}
新服务方式:
public get gradings$(): Observable<Grading[]> {
const observable = new BehaviorSubject([]);
this.gradingMetaQueries.selectAll().subscribe((gradings: Grading[]) => {
// not nice, but seems to do the job.
// Probably better ways available to copy object into mutable.
const thing = JSON.parse(JSON.stringify(gradings));
observable.next(thing);
});
return observable;
}