I have a matSelect
since I can select a number from 1 to 10, depending on the number I have to display the same number ofmatInput
with a *ngFor. The number selected by default in the select is 1 (so we have a one matInput
by default too)
<mat-form-field>
<mat-select placeholder="Number of winners to reward" [value]="selected" (selectionChange)="selectNumber($event)">
<mat-option *ngFor="let emailNumber of totalEmailsNumber" [value]="emailNumber">
{{ emailNumber }}
</mat-option>
</mat-select>
</mat-form-field>
<div formArrayName="mails">
<mat-form-field *ngFor="let email of form.get('mails').controls; let i = index">
<textarea matInput [formControlName]="i"></textarea>
</mat-form-field>
</div>
to add the default FormControl of the first MatInput
I do:
this.form.controls['mails'] = this.fb.array(this.emailsNumber.map(() => new FormControl('', Validators.required)));
Which works, but I can not manage the logic to add another FormControl
or to delete it if for example the user chose 10 in the select then changed it to 4,
and manage the binding in the template.
Im also wondering is *ngFor="let email of form.get('mails').controls
is a good practice?
Here's a Minimal StackBlitz Demo to work with
Give this a try:
import { Component, OnInit } from '@angular/core';
import { FormArray, FormBuilder, Validators } from '@angular/forms';
@Component({
selector: 'my-app',
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
form: FormGroup;
totalEmailsNumber: number[];
constructor(private fb: FormBuilder) {
}
ngOnInit() {
this.totalEmailsNumber = this.createCustomLengthArray(10);
this.form = this.fb.group({
mails: this.fb.array([])
});
}
get mails() {
return (<FormArray>this.form.controls['mails']);
}
selectNumber(emailNumbers) {
const difference = this.mails.length - emailNumbers;
difference > 0 ? this.removeMails(difference) : this.addMails(difference);
}
removeMails(difference) {
this.createCustomLengthArray(difference)
.forEach(item => this.mails.removeAt(this.mails.length - 1));
}
addMails(difference) {
this.createCustomLengthArray(difference)
.forEach(
item => {
this.mails.push(this.fb.control(null, Validators.required));
}
);
}
createCustomLengthArray(length) {
return (new Array(Math.abs(length)))
.fill(null)
.map((item, index) => index + 1);
}
}
And in the Template:
<form [formGroup]="form">
<mat-form-field>
<mat-select
placeholder="Number of winners to reward"
[value]="selected"
(selectionChange)="selectNumber($event.value)">
<mat-option
*ngFor="let emailNumber of totalEmailsNumber"
[value]="emailNumber">
{{ emailNumber }}
</mat-option>
</mat-select>
</mat-form-field>
<div formArrayName="mails">
<mat-form-field
*ngFor="let email of form.controls['mails'].controls; let i = index">
<textarea
matInput
[formControlName]="i">
</textarea>
</mat-form-field>
</div>
</form>
Here's a Working Sample StackBlitz for your ref.