【问题标题】:ngrx/store with ngModel caused some problemsngrx/store 和 ngModel 导致了一些问题
【发布时间】:2020-03-08 19:59:26
【问题描述】:

我正在使用primeng 可编辑表和ngrx/store。表值来自商店:results

父组件:

this.results$ = store.pipe(select(mySelectors.results));

使用 async 将其传递给子组件[results]="results$|async"

在子模板中:

<p-table [value]="results">
...
<ng-template pTemplate="body" let-rowData let-rowIndex="rowIndex">
  <tr [pSelectableRow]="rowData">
  ...
    <td pEditableColumn>
      <p-cellEditor>
        <ng-template pTemplate="input">
          <input pInputText type="text" [(ngModel)]="rowData.name">   // it's about this input
        </ng-template>
        <ng-template pTemplate="output">
          {{rowData.name}}
        </ng-template>
      </p-cellEditor>
    </td>
  </tr>
</ng-template>

结果模型是这样的:

{
 ...
 name: string;
 ...
}

我使用了ngrx-store-freeze。现在的问题是,商店的结果不能直接改变。因此,即使我尝试使用操作来更改商店中的值,但我无法从带有[(ngModel)]="rowData.name" 的输入标签中获取更改后的值,因为它是只读的。

那么如何从输入标签中获取更改后的值,或者有更好的方法吗?我知道 ngModel 与 ngrx/store 有点冲突,我尝试深拷贝 results 然后将其绑定到表,但它不起作用,深拷贝仍然是只读的。

我被困在这里了。请帮帮我

【问题讨论】:

  • 我不明白的最大问题是:store中的值是只读的,但是为什么我深拷贝后仍然无法修改它?

标签: javascript angular typescript redux ngrx


【解决方案1】:

Ngrx 存储冻结阻止您修改 rowData.names 的状态,因为您正在使用输入,这意味着您可以修改状态。

所以你可以通过删除 2 路绑定来修复它

<input pInputText type="text" [ngModel]="rowData.name"> 

【讨论】:

  • 是的,但是我还需要通过action来修改state中的值,如果我修改了input标签中的值,我什至无法获取值。获取值并将其绑定到输入是第一步,然后我需要在输入标签中键入一个新值并通过操作将新值更新到存储。
  • 如果你使用ngrx,你应该使用Reactiveform来获取不使用2路绑定的值
  • 这是正确的方法,但是使用primeng可编辑表格和反应形式存在更多问题,我已经尝试过,效果不好,也许我没有正确使用它,谢谢
【解决方案2】:

如果您想使用 ngModel 与来自 observable 的数据进行两种方式绑定,您应该在开始修改之前将其克隆到模板变量中。否则,您正在改变存储数据。我使用克隆管道

<ng-container *ngIf="results$ | async | clone as results">
  Do what you want with results as it wont mutate the store because it is a clone
</ng-container>

我的克隆管道看起来像

@Pipe({
  name: 'clone'
})
export class ClonePipe implements PipeTransform {
  transform(value: any, args?: any): any {
    return clone(value);
  }
}

克隆函数看起来像

export const clone = obj =>
  Array.isArray(obj)
    ? obj.map(item => clone(item))
    : obj instanceof Date
    ? new Date(obj.getTime())
    : obj && typeof obj === 'object'
    ? Object.getOwnPropertyNames(obj).reduce((o, prop) => {
        o[prop] = clone(obj[prop]);
        return o;
      }, {})
    : obj;

它不会克隆每个 JavaScript 对象,但对于通过 JSON 来自 API 的任何东西都可以。

【讨论】:

  • 我试过了,不管是用clonepipe还是直接从store中深拷贝结果,都不会改变只读属性,还是不能修改。
  • 那就不要冻结它,如果你不修改它就不需要冻结它。
  • 或者修改clone函数做非冻结克隆
【解决方案3】:

问题解决了。使用带有primeng 可编辑表的ngrx-store-freeze 可能存在一些错误。 退出 p-table 后,一切都会好起来的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-15
    • 2018-03-30
    • 1970-01-01
    相关资源
    最近更新 更多