I am trying to create functionality that maps some input fields to a model however it needs to be dynamic(there can be multiple repetitions of the image I have below).
The below image shows the design I am following
Explanation of flow
I have an input field called "current vehicle instalment" and a check box below it called "I am settling this account". If I click on the check box it will show 2 additional fields called "Account number" and "Financed by".
Then I have a button called "Add another vehicle instalment".
If I click this button it will add another vehicle input field called "Vehicle instalment 2" as well as another checkbox below it called "I am settling this account". If I click on the check box it will show 2 additional fields called "Account number" and "Financed by" that are related to vehicle 2.
I can have a maximum of 3 vehicles so once I add the 3rd vehicle I will no longer see the "Add another vehicle instalment" button
Here is my code so far
HTML
<div>
<form-input [dspRestrictedInput]="{type : 'numeric'}" [formStatus]="formStatus"
[parentFormGroup]="avafIncomeAndExpensesForm" [data]="formObjVehicleInstalment"
(onChange)="onValueChanged()"></form-input>
</div>
<div>
<form-checkbox [formStatus]="formStatus" [parentFormGroup]="avafIncomeAndExpensesForm"
[data]="settlecheckboxObj"> </form-checkbox>
</div>
<div *ngIf="showSettlementFields">
<form-input [formStatus]="formStatus"
[parentFormGroup]="avafIncomeAndExpensesForm" [data]="formObjAccountNumber"
(onChange)="onValueChanged()"></form-input>
</div>
<div *ngIf="showSettlementFields">
<form-dropdown [formStatus]="formStatus"
[parentFormGroup]="avafIncomeAndExpensesForm"
[data]="formObjFinancedBy"
(onChange)="onValueChanged()">
</form-dropdown>
</div>
<div (click)="addVehicleInstalment($event)">
<a><span ></span></a>
<h4>Add another vehicle instalment</h4>
</div>
TS
onChangeSettlecheckBox(value) {
if (value == true) {
//show additional fields when check box is selected
this.showSettlementFields = true;
}
}
addVehicleInstalment(event) {
//add next vehicle
this.isVehicleInstalmentClicked = true;
}
This is an example model that I must map each vehicle object to
"existingVehicleAccounts": [
{
"instalment": 1000,
"settle": true,
"accountNumber": "11111",
"financedBy": "Bank4"
},
{
"instalment": 2000,
"settle": false,
"accountNumber": "22222",
"financedBy": "Bank2"
},
{
"instalment": 3000,
"settle": true,
"accountNumber": "33333",
"financedBy": "Bank1"
}
]
I am currently trying to add the next vehicle section in my addVehicleInstalment
method. Any suggestions on how I can do this. I think I need to use indexes to identify which vehicle is for which object in my model.
I have added a very generic stackblitz example with just basic HTML functionality as I currently have it
CodePudding user response:
you should use FormArray
, where every item is a FormGroup
:
ngOnInit() {
this.vehicleForm = new FormGroup({
vehicleAccounts: new FormArray([]),
});
// start with one empty account
this.addInstalment();
}
addInstalment() {
const vehicleAccount = new FormGroup({
instalment: new FormControl(),
settle: new FormControl(false),
accountNumber: new FormControl(),
financedBy: new FormControl(),
});
this.vehicleAccounts.push(vehicleAccount);
}
Then, you define a getter to access this array in the template:
get vehicleAccounts() {
return this.vehicleForm.controls['vehicleAccounts'] as FormArray;
}
On every button click, you add a new FormGroup
to the array and let it display via ngFor
.
And this is the template:
<form [formGroup]="vehicleForm" (ngSubmit)="submit()">
<div formArrayName="vehicleAccounts">
<div
*ngFor="let vehicleAccountForm of vehicleAccounts.controls; let i = index"
>
<hr />
<div [formGroup]="vehicleAccountForm">
<div >
<label for="current">{{
i === 0
? 'current vehicle instalment'
: 'vehicle instalment ' (i 1)
}}</label>
<input type="text" id="current" formControlName="instalment" />
</div>
<input
type="checkbox"
id="settling-{{ i }}"
formControlName="settle"
(change)="changeSettling($event, i)"
/>
<label for="settling-{{ i }}">I'm settling this account</label>
<div *ngIf="vehicleAccountForm.controls['settle'].value">
<div >
<label for="accountNumber">account number</label>
<input
type="text"
id="accountNumber"
formControlName="accountNumber"
/>
</div>
<div >
<label for="financedBy">financed by</label>
<select id="financedByy" formControlName="financedBy">
<option value="bank 1">bank 1</option>
<option value="bank 2">bank 2</option>
<option value="bank 3">bank 3</option>
<option value="bank 4">bank 4</option>
</select>
</div>
</div>
</div>
</div>
<hr />
</div>
<button
(click)="addInstalment()"
[disabled]="vehicleAccounts.length === 3"
type="button"
>
add another vehicle instalment
</button>
<button type="submit">submit</button>
</form>
Check the stackblitz example here