Reputation: 1326
I have a table where it calls a child component called modal, modal component has two buttons save and cancel that are used for inline edit. I know I have to use "ChangeDetectorRef" but I cant figure out how to use the event "ngAfterViewInit" wit my code
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'disableEditSaveButton: false'. Current value: 'disableEditSaveButton: true'.
dashboard.HTML
<p-table #dt [value]="iToDoList" dataKey="id" [paginator]="true" [rowsPerPageOptions]="[10,50,100]"
[rows]="10">
<ng-template pTemplate="header">
<tr>
<th>ID</th>
<th>Comment</th>
<th>Action</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-row>
<tr>
<td>{{row.id}}</td>
<td>
<div *ngIf="!row.isEditable">{{row.comment}}</div>
<div *ngIf="row.isEditable">
<input type="text" [(ngModel)]="row.comment">
<span *ngIf="isEmpty(row.comment)" style="color:crimson">Required</span>
</div>
</td>
<td>
<div>
<modal [disableEditSaveButton]='disableSaveButton' (open)="onOpen(row)" [showModal]="!row.isEditable" (selectedRow)="onSelectedRow(row)" (cancelEdit)="onCancelEdit(row)"></modal>
</div>
<!--<button (click)="editRow(row)">Edit</button>-->
</td>
<td> <button (click)="save(row)">Save</button></td>
</tr>
</ng-template>
</p-table>
dashboard.compnent (this is causing ExpressionChangedAfterItHasBeenCheckedError)
isEmpty(input) {
if (input.replace(/\s/g, '') === "") {
this.disableSaveButton = true;
}
else {
this.disableSaveButton = false;
}
// this.cdr.detectChanges();
return input.replace(/\s/g, '') === "";
}
modal.html
<div *ngIf='!showModal'>
<button type="button" class="btn-xs btn-primary" (click)="onSave()" [disabled]='disableEditSaveButton'>Save</button>
<button type="button" class="btn-xs btn-orange" (click)="onCancelEdit()">Cancel</button>
</div>
modal.component
@Input() disableEditSaveButton: boolean = false;
******************UPDATE*************************************************************************
the browser it is still throwing ExpressionChangedAfterItHasBeenCheckedError
Component
isEmpty(input) {
this.cdr.detach();
if (input.replace(/\s/g, '') === "") {
this.disableSaveButton = true;
}
else {
this.disableSaveButton = false;
}
// this.cdr.detectChanges();
// restart change detection for this view
this.cdr.reattach();
return input.replace(/\s/g, '') === "";
}
Upvotes: 0
Views: 865
Reputation:
Okay, so here comes another approach.
Analysing your code I could see that
this.disableSaveButton === isEmpty(row.comment)
This means that, if isEmpty(row.comment)
is true, this.disableSaveButton
is true too and the other way round.
So why don't you directly use the result of isEmpty(row.comment)
instead of storing it into this.disableSaveButton
? Doing this you have no changing expression as the first true or false will also be the last.
Please, try it this way:
<modal [disableEditSaveButton]='isEmpty(row.comment)'
(open)="onOpen(row)"
[showModal]="!row.isEditable"
(selectedRow)="onSelectedRow(row)"
(cancelEdit)="onCancelEdit(row)">
</modal>
And if you don't need this.disableSaveButton
for other purposes than your modal dialogue, which means you don't need it at all now, you could shrink the size of your method to this, without changing it's logical outcome.
isEmpty(input) {
return input.replace(/\s/g, '') === "";
}
Upvotes: 1
Reputation:
Try it this way:
isEmpty(input) {
// stop change detection for this view
this.cdr.detach();
if (input.replace(/\s/g, '') === "") {
this.disableSaveButton = true;
}
else {
this.disableSaveButton = false;
}
// this.cdr.detectChanges();
// restart change detection for this view
this.cdr.reattach();
return input.replace(/\s/g, '') === "";
}
Upvotes: 0