0

我有一个秋田商店,里面装满了来自服务器的数据。我正在尝试从商店获取一个对象并使用角度双向绑定 [()] 对其进行编辑。

每当我尝试更改对象的值时(在模板 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;
  }

4

1 回答 1

0

虽然我不使用秋田,但我确实有使用 immer 的经验。我看不到你在哪里做“生产”功能。

基于 immer 上来自 akita 的文档。看起来他们扩展了producewith的功能update

这方面的一些东西应该会更新你的状态的价值。

    this.gradingMetaStore.update(draft => {

        draft.[1].examiners[1].firstName = 'william';

    }
于 2022-01-22T02:15:12.770 回答