This is continuation to my original issue
stackoverflow.com/questions/44596418/angular-throws-expressionchangedafterithasbeencheckederror-with-textarea
which is still unresolved. I recreated the orignal plunkr to simulate the actual project and found it is nothing related to the textarea.
When I go to details page by clicking on a item from the list,the exception ExpressionChangedAfterItHasBeenCheckedError is thrown. This happens only when the CodeView of src/detailitems.ts has more than one element in the array. The CodeView items defines the fields in detail form.
import { FormBase } from './formbase'
import { ItemBase, TextboxItemBase } from './itembase'
export class CodeView extends FormBase {
static getItems() :ItemBase[] {
let items: ItemBase[] = [
new TextboxItemBase(
{
key: 'id',
label: 'ID',
value: '',
required: true,
enabled: false,
readOnly: true,
size: 36
}
)
,
new TextboxItemBase(
{
key: 'description',
label: 'Description',
required: true,
size: 20
}
)
];
return items;
}
}
If I modify the code so that the CodeView has only 1 item, then the exception goes away.
Exception Plunkr
No Exception Plunkr (Just one item in detailitems)
Your error comes from A-Item
component more precisely from this node
<div [formGroup]="form"
when you have such binding angular will automatically create NgControlStatusGroup
directive that sets CSS classes based on control status (valid/invalid/dirty/etc).
export const ngControlStatusHost = {
'[class.ng-untouched]': 'ngClassUntouched',
'[class.ng-touched]': 'ngClassTouched',
'[class.ng-pristine]': 'ngClassPristine',
'[class.ng-dirty]': 'ngClassDirty',
'[class.ng-valid]': 'ngClassValid', // you get error in this binding
'[class.ng-invalid]': 'ngClassInvalid',
'[class.ng-pending]': 'ngClassPending',
};
At first time you don't provide any value for your controls. That's why valid
property for your form is false
. Then you populate it by using ngModel
during change detection cycle and form becames valid. Valid property for form
is calculated from all your controls. If you have only one control then valid property will depend only on one control and A-Item
component won't raise error.
I would prepare data before rendering.
You can open form.component.ts and find the following code
this.formItems.forEach(item => {
group[item.key] = item.BuildControl();
this.items.push(new formObjectItem(item, this.getData(item.key)));
});
then you need to patch data for form
this.formItems.forEach(item => {
group[item.key] = item.BuildControl();
this.items.push(new formObjectItem(item, this.getData(item.key)));
group[item.key].patchValue(this.getData(item.key)); // <== this line
});
or
this.formItems.forEach(item => {
group[item.key] = item.BuildControl();
const value = this.getData(item.key);
this.items.push(new formObjectItem(item, value));
group[item.key].patchValue(value);
});
This way your form will be synchronized with your value and will have correct status.
In this case you can also remove itemValue
and ngModel
from A-Item
component since reactive model will do all work.
Forked Plunker
You don't get such error
One more tips:
import * as Rx from 'rxjs/Rx'
you will ship all rxjs library to your bundle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With