I tried to have 2 nested forms using CVA. the problem is the second from isn't initialized with data when I bind it to a formControl.
I have MAIN-FORM:
this.requestForm = this.fb.group({
garageId: 0,
routes: new FormArray([
new FormGroup({
addressPointId: new FormControl,
municipalityId: new FormControl,
regionId: new FormControl,
rvId: new FormControl,
sequenceNumber: new FormControl,
settlementId: new FormControl,
regionName: new FormControl,
municipalityName: new FormControl,
settlementName: new FormControl,
description: new FormControl,
})
]),
endDateTime: 0,
});
In main-form html I bind routes to with formArrayName.
<app-cva-form-array formArrayName="routes"></app-cva-form-array>
Component CVA-FORM-ARRAY has.
form = new FormArray([
new FormGroup({
addressPointId: new FormControl,
municipalityId: new FormControl,
regionId: new FormControl,
rvId: new FormControl,
sequenceNumber: new FormControl,
settlementId: new FormControl,
regionName: new FormControl,
municipalityName: new FormControl,
settlementName: new FormControl,
description: new FormControl,
})
]);
Everything from here works just fine. I bind each formGroup in the array to child component CVA-FORM.
<app-cva-form [formControl]="route" (blur)="onTouched()"></app-cva-form>
CVA-FORM for each formGroup I created separate component in case I want to use component itself not the whole array.
form: FormGroup = new FormGroup({
regionName: new FormControl,
regionId: new FormControl,
municipalityName: new FormControl,
municipalityId: new FormControl,
sequenceNumber: new FormControl,
settlementName: new FormControl,
settlementId: new FormControl,
addressPointId: new FormControl,
description: new FormControl,
rvId: new FormControl,
});
the main-form <--to--> app-cva-form-array binding doesn't work for some reason.
The idea of these forms comes from kara's talk on angulaconnect. here are her slides.
help plz!
When you use "custom Form Control", you need take account that you feed the cursom Form Control with a Form Control (not FormArray, not FormGroup). The FormControl has as value an array or an object, but you need not confussed about this.(*)
You can see in work in stackblitz
That's your form is like
I've create a const to export to simply the code. MY const expor is
So, in mainForm we have
In cvc-form array create the formArray when we give value
Finally, the cva-form
(*) Yes, we are used to seeing that a FormControl has as a value a string or a number, but no one forbids us that the value is an object or an array (for example, ng-bootstrap DatePicker stores an object {year: .. month: .., day ..}, mat-multiselect stores an array, ...)
Update Of course we can feed our control with data from a service or similar. The only thing we must take account is how we give the data. As usually I like make a function that received a data or null and return a FormControl
where IData is an interface
and IDetail another interface
Then we can have a complex data like (sorry for the large object)
Then only need make
The stackblitz if updated
I believe the issue here is that
formArrayName
is not an input forNG_VALUE_ACCESSOR/DefaultValueAccessor
.Also note:
Exploring how to iterate over the
FormArray
at theparent
level and instantiate yourchild->grandchild
relationship from within that loop may be a possible solution, this way you are not passing the entire array down, only theformGroup
that would apply.Selectors
https://angular.io/api/forms/DefaultValueAccessor#selectors
Your only options for input are
formControlName
,formControl
,ngModel
andngDefaultControl
...I believe the key to understand here is that
formArray
is only an organizational container for its children... it will not do what you are wanting it to in this scenario without help from additional logic.You need to pass the updated form data from Child Component to Parent Component. I have used
this.form.valueChanges()
method to detect the changes and then emit the Form value to the parent component.HTML Code:
TS Code:
HTML Code:
TS Code:
and call
registerEvent
method in the constructor like:Working_Stackblitz