I've built a custom input component with ControlValueAccessor and it works great to add tags as selections. (Stackblitz)
My problem is:
Here is a screenshot of two of the same component's values after submitting the angular form. One is an array of objects (expected) the other is an actual FormArray object which .value property contains the array of objects!
Here is some code of how it works in case you don't want to visit StackBlitz.
The custom control is implemented like this.
this.form = this.fb.group({
tags: this.fb.array([])
});
When the user selects a dropdown item or hits enter the object is saved like this:
get tagsArray(): FormArray { return this.form.get('tags') as FormArray; }
...
this.tagsArray.push(new FormControl(value));
this.onChange(this.tagsArray); // update controller value
You could replicate this by implementing the component in my StackBlitz in a formGroup just like this (also in my StackBlitz):
Form Init
public form: FormGroup = this.fb.group({
states: [],
cities: []
});
Template
<input-tags formControlName="cities" label="Cities" [typeAhead]="cities" [displayKeys]="['name']" filterKeys="['name']"></input-tags>
<input-tags formControlName="states" label="States" [typeAhead]="states" [displayKeys]="['name']" filterKeys="['name']"></input-tags>
but the question is:
When is Angular's FormArray a traditional array and when is it a FormArray Array like object?
A FormArray aggregates the values of each child FormControl into an array. It calculates its status by reducing the status values of its children. For example, if one of the controls in a FormArray is invalid, the entire array becomes invalid.
Binding FormArray to Template We use the formArrayName directive to bind the skills form array to the div element. Now the div and anything inside the div element is bound to the skills form array. Inside the div use ngFor to loop through each element of skills FormArray.
Whereas FormGroup represents an entire form or a fixed subset of a form's fields, FormArray usually represents a collection of form controls that can grow or shrink.
FormArray
object is being created when you create a control instance using new FormArray([])
or formBuilder.array([])
.
However, if you apply a FormControl
instance to class with ControlValueAccessor
methods it will write either FormControl
or FormGroup
(if you want to work with provided by Angular form objects) to the value of control you have passed.
Thus, in first case you get a FormArray
object and in second case you can get either regular JS types (object, array, string etc.) or FormGroup
/FormControl
.
If you want more expanded answer specific to your case the code sample is required because your implementation may cause transforming array to FormArray
at some point.
If we change a valueChanges
from users
to form
we can see that this form is kind of broken, because .value
gives us another FormArray
instead of just Array.
Also, I've checked the implementation and there is nowhere you can get regular array in there. However, custom control is implemented wrong IMHO, since you should the value on .value
instead of FormArray
or whatever similar to this.
Therefore, if you can change the implementation of this control I would suggest you do that. I do it in way of
registerOnChange(fn: any): void {
this.tagsArray.valueChanges.subscribe(fn);
}
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