Dynamic form arrays

Note that phones is an array, potentially allowing for many inputs. We can implement this by building a FormArray with this.formBuilder.array and with several helper functions:

src/app/user/profile/profile.component.ts
...
phones: this.formBuilder.array(this.buildPhoneArray(user ? user.phones : [])),
...
private buildPhoneArray(phones: IPhone[]) {
const groups = []

if (!phones || (phones && phones.length === 0)) {
groups.push(this.buildPhoneFormControl(1))
} else {
phones.forEach(p => {
groups.push(this.buildPhoneFormControl(p.id, p.type, p.number))
})
}
return groups
}

private buildPhoneFormControl(id, type?: string, number?: string) {
return this.formBuilder.group({
id: [id],
type: [type || '', Validators.required],
number: [number || '', USAPhoneNumberValidation],
})
}
...

BuildPhoneArray supports initializing a form with a single phone input or filling it with the existing data, working in tandem with BuildPhoneFormControl. The latter function comes in handy when a user clicks on an Add button to create a new row for entry:

src/app/user/profile/profile.component.ts
...
addPhone() {
this.phonesArray.push(
this.buildPhoneFormControl(this.userForm.get('phones').value.length + 1)
)
}

get phonesArray(): FormArray {
return <FormArray>this.userForm.get('phones')
}
...

The phonesArray property getter is a common pattern to make it easier to access certain form properties. However, in this case, it is also necessary, because get('phones') must be typecast to FormArray so that we can access the length property on it on the template:

src/app/user/profile/profile.component.html
...
<mat-list formArrayName="phones">
<h2 mat-subheader>Phone Number(s)</h2>
<button mat-button (click)="this.addPhone()">
<mat-icon>add</mat-icon>
Add Phone
</button>
<mat-list-item *ngFor="let position of this.phonesArray.controls let i=index" [formGroupName]="i">
<mat-form-field fxFlex="100px">
<mat-select placeholder="Type" formControlName="type">
<mat-option *ngFor="let type of this.PhoneTypes" [value]="type">
{{ type }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex fxFlexOffset="10px">
<input matInput type="text" placeholder="Number" formControlName="number">
<mat-error *ngIf="this.phonesArray.controls[i].invalid">
A valid phone number is required
</mat-error>
</mat-form-field>
<button fxFlex="33px" mat-icon-button (click)="this.phonesArray.removeAt(i)">
<mat-icon>close</mat-icon>
</button>
</mat-list-item>
</mat-list>
...
The remove function is implemented inline.

Let's see how it should be working:

Multiple inputs using FormArray

Now that we're done with inputing data, we can move on to the last step of the stepper, Review. However, as it was mentioned earlier, the Review step uses the app-view-user directive to display its data. Let's build that view first.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.20.224.107