Reputation: 6769
Assume I had the following form group:
this.cvForm = this._fb.group({
name: ['', [Validators.required]],
lastname: ['', [Validators.required]],
nested: this._fb.group({
level1: this._fb.group({
level2: this._fb.group({
checkbox: [this.checkbox, Validators.required] // this.checkbox is boolean value (initial value = false)
})
}),
}),
});
And then I assign the checkbox value to true (this.checkbox = true;
).
When I assign manually to the form group without using patchValue
:
this.cvForm.value.nested.level1.level2.checkbox = this.checkbox;
and observe the value: console.log('a',this.cvForm.value.nested.level1.level2.checkbox) // return true
It returns true but the checkbox wasn't checked.
But when I use patchValue
:
this.cvForm.patchValue({
nested: {
level1: {
level2: {
checkbox: this.checkbox
}
}
}
});
and observe the value: console.log('b',this.cvForm.value.nested.level1.level2.checkbox) // return true
It returns true and the checkbox was checked.
From patchValue()
docs:
Patches the value of the FormGroup. It accepts an object with control names as keys, and does its best to match the values to the correct controls in the group.
Does this mean when you manually assign the value it wouldn't reflect to the form as patchValue
does? What is the difference between the two?
Upvotes: 1
Views: 1656
Reputation: 11979
This happens because patchValue
(just like setValue
) does a little more work under the hood.
// For a `FormControl` instance
patchValue(value: any, options: {
onlySelf?: boolean,
emitEvent?: boolean,
emitModelToViewChange?: boolean,
emitViewToModelChange?: boolean
} = {}): void {
this.setValue(value, options);
}
setValue(value: any, options: {
onlySelf?: boolean,
emitEvent?: boolean,
emitModelToViewChange?: boolean,
emitViewToModelChange?: boolean
} = {}): void {
(this as{value: any}).value = this._pendingValue = value;
if (this._onChange.length && options.emitModelToViewChange !== false) {
this._onChange.forEach(
(changeFn) => changeFn(this.value, options.emitViewToModelChange !== false));
}
this.updateValueAndValidity(options);
}
Where onChange
function will look like this
function setUpModelChangePipeline(control: FormControl, dir: NgControl): void {
control.registerOnChange((newValue: any, emitModelEvent: boolean) => {
// control -> view
dir.valueAccessor !.writeValue(newValue);
// control -> ngModel
if (emitModelEvent) dir.viewToModelUpdate(newValue);
});
}
dir.valueAccessor !.writeValue(newValue);
is what reflects the change of the model(e.g: FormControl
) into the view(a DOM element).
CheckboxValueAccessor.writeValue
writeValue(value: any): void {
this._renderer.setProperty(this._elementRef.nativeElement, 'checked', value);
}
I've recently written an article "A thorough exploration of Angular Forms" in which I try to explain how all things are set up when using forms.
Upvotes: 2