-
Notifications
You must be signed in to change notification settings - Fork 24.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Form patchValue method throws unnecessary error #36672
Comments
Hi @edusoccer1121, thanks for providing a repro. According to the type definition of the angular/packages/forms/src/model.ts Line 1470 in a62c1c4
the null and undefined values (that you try to use as an argument) are not supported and should actually trigger a TypeScript error. I've updated your repro (new repro is available here) to set an explicit type for the errorFormValue field and now you can see that the TypeScript error is produced. It looks like Framework works as expected and no additional handling inside the patchValue function is required (as these values are not supported by the function type definition), so I will close this ticket. Thank you.
|
@AndrewKushnir you welcome. Does this means I cannot received a property with null value and use the method, since it will fail and not update the form? In a API response with a null property the method would not update correctly the form. Meaning I would have to check each prop before using the patchValue method ? Guidance on how to proceed when I can't control or check for nullness of every property on the value passed to the function. |
Hi @eduardosivd, thanks for additional information, I see your point now (I was confused originally due to the fact that a sub-group was passed into the I will re-open this ticket, so we can discuss it further. Thank you. |
angular/packages/forms/src/model.ts Lines 1558 to 1566 in 062b8d9
would a fix be something like: patchValue(value: {[key: string]: any}, options: {onlySelf?: boolean, emitEvent?: boolean} = {}):
void {
if (value === null || value === undefined) { this.reset(options); } // or return? semantics not clear
Object.keys(value).forEach(name => {
if (this.controls[name]) {
this.controls[name].patchValue(value[name], {onlySelf: true, emitEvent: options.emitEvent});
}
});
this.updateValueAndValidity(options);
} Or would it be better to introduce a stricter type: interface RecursiveRecord {
[K: string]: string | boolean | number | RecursiveRecord | string[] | boolean[] | number[] | RecursiveRecord[]
} though this could break code which currently does function using |
Hi all, we have the exact same problem in our solution. Our api may return null-values for child @bbarry: Thanks for your suggestion. It's indeed an interesting question how to handle this case. In my opinion you could either call patchValue(value: {[key: string]: any}, options: {onlySelf?: boolean, emitEvent?: boolean} = {}):
void {
if (value !== null && value !== undefined) {
Object.keys(value).forEach(name => {
if (this.controls[name]) {
this.controls[name].patchValue(value[name], {onlySelf: true, emitEvent: options.emitEvent});
}
});
this.updateValueAndValidity(options);
}
} In my opinion, doing nothing would still align well with the method's purpose as described in the docs:
Doing nothing would in this context mean we update all the fields and data that are available and leave all other fields unchanged. I guess this would also have less side effects in respect of existing applications. @AndrewKushnir In my opinion the priority is a little higher ;) Actually, you can't use formGroup.patchValue as soon as you have an optional child object in your data that is |
Thanks for additional information @jpett. I think the
Given that the Currently I'm leaning towards having a more descriptive error message (vs just crashing on trying to iterate over undefined values) thrown from the |
Thanks @AndrewKushnir for your elaborate response. I definitely see your point. However, I think the current implementation has the inherent problem that you cannot manage objects with nullable object properties which is a pretty common case when modelling business objects. Just consider something like a customer who may optionally provide a billingAddress: interface Customer {
id: number;
firstname: string;
lastname: string;
shippingAddress: Address;
billingAddress: Adress | null;
} Currently, you cannot create FormGroups for this interface and patch customer data with a billingAddress of if (customer.billingAddress === null) {
customer.billingAddress = {};
} Both solutions feel not really elegant. I think if we would change
I am aware (and thankful!) that your team has to think a lot about breaking/changing behaviour of existing code. The only change of behaviour I can think of in this case is that currently patchValue might be interrupted by the error that is being thrown, which might result in a FormGroup that is only partly patched. It depends on the order of the Sample FormGroup 1:this.formGroup = this.formBuilder.group({
firstname: null,
lastname: null,
shippingAddress: this.formBuilder.group({...}),
billingAddress: this.formBuilder.group({...})
}); If we patch customerData with a billingAddress of Sample FormGroup 2:this.formGroup = this.formBuilder.group({
billingAddress: this.formBuilder.group({...}),
firstname: null,
lastname: null,
shippingAddress: this.formBuilder.group({...})
}); Patching the customerData into this Obviously, there are also cases were the relevant FormGroup is somewhere in between which would result in a form that is only partly filled. So Sample FormGroup 1 resembles a special case that 'accidentally' results in a correctly filled form. I don't see that anybody would knowingly make use of try {
this.formGroup.patchValue();
}
catch {
// Handle error explicitly
} I would definitely expect people writing code like this when using Sorry for getting into so much detail about this but writing everything down just helped me realising some of the implications :) TLDRIn summary, I see your point, but as described above I also think that a One last thing: Looking at the angular roadmap I saw this very exciting point: Better developer ergonomics with strict typing for @angular/forms That would definitely be a great feature and I think it would be even better if it would also support nullable object properties. ;) Thanks again for your great work! |
…classes to skip `null` values Prior to this commit, the `patchValue` of the `FormGroup` and `FormArray` classes used to throw an exception when the `value` argument contained a data structure that has `null` or `undefined` as a value for a field that represents an instance of `FormGroup` or `FormArray` (for `FormControl` it's not a problem, since it doesn't have nested controls), since the `patchValue` method tried to iterate over provided value to match current data structure. This commit updates the `patchValue` logic in `FormGroup` and `FormArray` classes to just ignore `null` and `undefined` values (without any changes to corresponding `FormGroup` and `FormArray` instances). This behavior looks oinline with the `patchValue` method goal of "doing its best to match the values to the correct controls" (quote from docs). Fixes angular#36672. Fixes angular#21021.
…classes to skip `null` values Prior to this commit, the `patchValue` of the `FormGroup` and `FormArray` classes used to throw an exception when the `value` argument contained a data structure that has `null` or `undefined` as a value for a field that represents an instance of `FormGroup` or `FormArray` (for `FormControl` it's not a problem, since it doesn't have nested controls), since the `patchValue` method tried to iterate over provided value to match current data structure. This commit updates the `patchValue` logic in `FormGroup` and `FormArray` classes to just ignore `null` and `undefined` values (without any changes to corresponding `FormGroup` and `FormArray` instances). This behavior looks inline with the `patchValue` method goal of "doing its best to match the values to the correct controls" (quote from docs). Fixes angular#36672. Fixes angular#21021.
…` classes to skip `null` values Prior to this commit, the `patchValue()` of the `FormGroup` and `FormArray` classes used to throw an exception when the `value` argument contained a data structure that has `null` or `undefined` as a value for a field that represents an instance of `FormGroup` or `FormArray` (for `FormControl` it's not a problem, since it doesn't have nested controls), since the `patchValue()` method tried to iterate over provided values to match current data structure. This commit updates the `patchValue()` logic in `FormGroup` and `FormArray` classes to just ignore `null` and `undefined` values (without any changes to corresponding `FormGroup` and `FormArray` instances). This behavior looks inline with the `patchValue()` method goal of "doing its best to match the values to the correct controls" (quote from docs). Fixes angular#36672. Fixes angular#21021.
…` classes to skip `null` values (#40534) Prior to this commit, the `patchValue()` of the `FormGroup` and `FormArray` classes used to throw an exception when the `value` argument contained a data structure that has `null` or `undefined` as a value for a field that represents an instance of `FormGroup` or `FormArray` (for `FormControl` it's not a problem, since it doesn't have nested controls), since the `patchValue()` method tried to iterate over provided values to match current data structure. This commit updates the `patchValue()` logic in `FormGroup` and `FormArray` classes to just ignore `null` and `undefined` values (without any changes to corresponding `FormGroup` and `FormArray` instances). This behavior looks inline with the `patchValue()` method goal of "doing its best to match the values to the correct controls" (quote from docs). Fixes #36672. Fixes #21021. PR Close #40534
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
🐞 bug report
Affected Package
The issue is caused by package @angular/....The issue is caused by @angular/forms
Is this a regression?
I don't think so.
Description
When the patchValue method on a form which contains a form group and the value passed is equal to null or undefined, error is thrown.
🔬 Minimal Reproduction
https://stackblitz.com/edit/angular-issue-repro2-hxfefx
🔥 Exception or Error
🌍 Your Environment
Angular Version:
Anything else relevant?
The text was updated successfully, but these errors were encountered: