I've created a reactive form based on the data I receive from a REST API and also static content. Once the user submits the form the data is sent. I have one section where the property name of a formControl is the same name. e.g.
<ng-container formArrayName="documentFields">
<ng-container *ngFor="let doc of documentFields(comIndex).controls; let skillIndex=index">
<ng-container [formGroupName]="skillIndex">
<div class="row mb-3">
<label class="col-sm-1 col-form-label">Category:</label>
<div class="col-md-2">
<ng-container>
<select id="" class="form-select" formControlName="value">
<option selected>Select</option>
<option *ngFor="let c of taxonomyResponse.categoryList">{{c.name}}</option>
</select>
</ng-container>
</div>
<label class="col-auto col-form-label">Sub-Category:</label>
<div class="col-md-2">
<select id="" class="form-select" formControlName="value">
<option selected>Select</option>
</select>
</div>
</div>
</ng-container>
</ng-container>
</ng-container>
As you can see "value" is called twice. In order for the POST request to work these property filed need to be the same. Here is my method.
newDocumentFields() {
return this.fb.group({
name: '',
value: '',
})
}
And this is how the response should look when sending the POST
"documents": [
{
"name": "1.pdf",
"documentId": 34,
"documentFields": [
{
"name": "",
"value": ""
},
{
"name": "",
"value": ""
}
]
]
The "value" will have data from a service call but the "name" will be static.
Technically within a FormGroup
/object
, you can't have multiple keys with the same name.
Based on your expected result, within the documentFields
array, it will have 2 FormGroup
/object
(s), the first one will be Category and followed by the Sub-Category.
You are required to use 2 FormGroups instead of a single FormGroup
.
Your documentFields
FormArray structure should be as below:
<ng-container formArrayName="documentFields">
<ng-container
*ngFor="let skillIndex of documentFieldsIndexes(comIndex);"
>
<div class="row mb-3">
<label class="col-sm-1 col-form-label">Category:</label>
<div class="col-md-2">
<ng-container [formGroupName]="skillIndex">
<select id="" class="form-select" formControlName="value">
<option selected>Select</option>
<option *ngFor="let c of taxonomyResponse.categoryList">
{{c.name}}
</option>
</select>
</ng-container>
</div>
<label class="col-auto col-form-label">Sub-Category:</label>
<div class="col-md-2">
<ng-container [formGroupName]="skillIndex + 1">
<select id="" class="form-select" formControlName="value">
<option selected>Select</option>
</select>
</ng-container>
</div>
</div>
</ng-container>
</ng-container>
For the iteration (*ngFor
) part, you need to iterate every 2 elements in order to make each iteration will have 2 elements. Thus, there is why the below function is needed with:
documentFields
array by 2.*ngFor
, the values (indexes) will be started from 0 and incremented by 2. Example: 0, 2, 4...documentFieldsIndexes(comIndex: number) {
return Array(this.documentFields(comIndex).controls.length / 2)
.fill(0)
.map((x, i) => i * 2);
}