Reputation: 11
I'm using primeng editable table and ngrx/store. The table value is from store: results
.
The parent component:
this.results$ = store.pipe(select(mySelectors.results));
use async to pass it to child componnet [results]="results$|async"
.
In the child template:
<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>
the results model is like this:
{
...
name: string;
...
}
I used ngrx-store-freeze
. now the question is,the results from store cannot be changed directly. So even if I tried to use action to change values in the store, but I cannot get the changed value from the input tag with [(ngModel)]="rowData.name"
, cause it's read only.
So how can I get the changed value from input tag, or is there a better way to do this? I understand that ngModel is sort of conflict with ngrx/store, and I tried to deep copy results
then bind it to the table, but it's not working, the deep copy is still read only.
I'm stuck here. please help me
Upvotes: 1
Views: 2695
Reputation: 11
problem solved. There may be some bugs using ngrx-store-freeze with primeng editable table. when out of p-table, all will be ok.
Upvotes: 0
Reputation: 21658
If you want to use ngModel to two way bind with data that comes from an observable you should clone it into a template variable before you start modifying it. Otherwise you are mutating the store data. I use a clone pipe
<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>
My clone pipe looks like
@Pipe({
name: 'clone'
})
export class ClonePipe implements PipeTransform {
transform(value: any, args?: any): any {
return clone(value);
}
}
and the clone function looks like
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;
It wont clone every JavaScript object but will be fine for anything that came from an API via JSON.
Upvotes: 0
Reputation: 20162
Ngrx store freeze prevent you to modify the state of the rowData.names
because you are using input which mean you can modify the state.
So you can fix it by remove 2 way binding
<input pInputText type="text" [ngModel]="rowData.name">
Upvotes: 1