I'm submitting a ... (check one with "x")
[ x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request
Current behavior
Using the same keys for different separate forms on the same page formly could trigger an error under some circumstances:
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'disabled: false'. Current value: 'disabled: true'
This happens in an application using angular material when I have one form open on the page and then open the other instance inside an modal.
If I create an copy (via JSON.parse(JSON.stringify(val))) of the config inside the modal I get a onverting circular structure to JSON error. If I create a copy at both of the instances everything runs fine.
Expected behavior
Using the same config for different forms should not lead to errors.
Minimal reproduction of the problem with instructions
While so far unable to create a blitz which reproduces the exact issue I am having, I'll made another one: https://stackblitz.com/edit/ngx-formly-ui-material-fngtya
If you click on the checkbox of the second form, the checkbox of the first form is focused. I am assuming that this connection leads to the error.
It should be possible to reproduce the described behavior exactly in this repo: https://github.com/johannesjo/super-productivity/commit/1fab8ef2df92f8004dc364d61a560e8c9149ec50#commitcomment-32363809
Angular version: 7.2.X
Browser: all (I guess)
Language: all (I assume)
I'll try to dig a little deeper. Thanks for this very cool module.
If I create an copy (via
JSON.parse(JSON.stringify(val))) of the config inside the modal I get aonverting circular structure to JSONerror. If I create a copy at both of the instances everything runs fine.
just fixed an issue related to that part today which is landed in 5.0.0-rc.4
Using the same config for different forms should not lead to errors.
i'll investigate on it
passing an object to different fields means they share the same ref.
fields = FORM_CONFIG // copy the reference (not the value!) of `FORM_CONFIG` to `fields`
fields2 = FORM_CONFIG // copy the reference of `FORM_CONFIG` to `fields2`
console.log(fields === fields2) // => true
instead, declare FORM_CONFIG as a function which allows you to return a new copy of fields whenever is needed:
export const FORM_CONFIG = () => [
...
];
...
export class AppComponent {
...
fields = FORM_CONFIG();
}
here is working example https://stackblitz.com/edit/ngx-formly-ui-material-re5rzg?file=app%2Fapp.component.ts
@aitboudad wouldn't it maybe be better to assure this on formly's side? I would usually think of any config as stupid read only data object where nothing like instances or object equality matters.
normally we shouldn't touch the original fields (that's a mistake, the same for model input), changing that behavior would break some apps and require some time to be implemented in a proper way but I think we should go for it to avoid those side effects.
for now we can add a new input [immutable]="true" to enable that mode.
it should be landed in 5.0.0-rc.6, all you've to do is to pass immutable attr and to track the model value changes you may use modelChange output.
for a smooth upgrade you can use:
-- <formly-form [model]="model" ...
++ <formly-form [model]="model" immutable (modelChange)="model = $event"` ...
FYI it seems like that the immutable property is missing from formly.form.d.ts
not missing :), I've defined that prop as an attribute.
note: you can enable immutable mode globally through NgModule declaration too:
@NgModule({
imports: [
FormlyModule.forRoot({
extras: { immutable: true }
}),
],
})
Ah ok. Thanks :) My poor old IDE got confused...
The global config option is a great idea!
Even with 5.1.7 and everything set to immutable, there is still is weird stuff going on. When I only have one form everything works fine. If I open up another with the same config and enter something into the second form the input immediatly looses focus and the page scrolls down.
I would like to provide another blitz, but it seems like the new version of formly isn't compatible to ng5 anymore and after trying to update all the ng depdencies by hand, i got a little frustrated...
I'll check it on my side, got the repo https://github.com/johannesjo/super-productivity :)
Yap. =)
Meanwhile i created a new blitz (using my project depdencies):
https://stackblitz.com/edit/ngx-formly-ui-material-zgltfs
working on a fix that should be part of 5.1.8,
for the migration sent a PR https://github.com/johannesjo/super-productivity/pull/175
Don't know if this helpful, but this is my workaround for now: https://github.com/johannesjo/super-productivity/commit/0710fc1debd96a8651ce208109edf729ebcc021b
5.1.8 released that fix the weird issue :smiley:
Seems to work. I even tried to understand why, but maybe it's a little bit to late at night for this :D
Thank you very much!
Edit: The forms even seem to render a bit faster! So that's cool.
Edit: The forms even seem to render a bit faster! So that's cool.
that's cool, whenever you noticed something wrong in formly don't hesitate to fill an issue!
my plan is to make formly suitable for everyone :1st_place_medal:
Seems to work. I even tried to understand why, but maybe it's a little bit too late at night for this :D
whenever a model change event is triggered we perform a deep clone unintentionally for the fields instance which rebuild the form and cause a re-render of the field template.
whenever a model change event is triggered we perform a deep clone unintentionally for the fields instance which rebuild the form and cause a re-render of the field template.
This makes sense. Thanks for the explanation!
Most helpful comment
that's cool, whenever you noticed something wrong in
formlydon't hesitate to fill an issue!my plan is to make
formlysuitable for everyone :1st_place_medal:whenever a model change event is triggered we perform a deep clone unintentionally for the
fieldsinstance which rebuild the form and cause a re-render of the field template.