How To Assign And Validate Arrays To Forms In Angular2
Solution 1:
How should I bind an array from model to UI?
Well, I'd prefer to push all the emails from profile.emails
to the formArray
, otherwise you'll have the values, but no validation.
How should I validate the length of array?
You can use the Validators.minLength(Number)
as any other control.
Demo code:
Component:
export class AnyComponent implements OnInit {
profileForm: FormGroup;
emailsCtrl: FormArray;
constructor(private formBuilder: FormBuilder) { }
ngOnInit(): void {
this.emailsCtrl = this.formBuilder.array([], Validators.minLength(ANY_NUMBER));
this.profile.emails.forEach((email: any) => this.emailsCtrl.push(this.initEmail(email)));
this.profileForm = this.formBuilder.group({
// ... other controls
emails: this.emailsCtrl
});
}
private initEmail = (obj: any): FormGroup => {
return this.formBuilder.group({
'email': [obj.email], //, any validation],
'isDefault': [obj.isDefault] //, any validation]
});
}
}
Template:
<div *ngFor="let emailInfo of emailsCtrl.value">
{{emailInfo.email}}
<button (click)="removeEmail(emailInfo)">
Remove
</button>
</div>
<div *ngIf="emailsCtrl.hasError('minlength')">
It should have at least {{emailsCtrl.getError('minlength').requiredLength}} emails
</div>
PS1: Note that the param of Validators.minLength(param)
method must be greater than 1, otherwise it won't validate.
As you can see in source when the control is empty it automatically returns null.
Then, to make it work as you expected you could add the required
Validator:
this.emailsCtrl = this.formBuilder.array([], Validators.compose([Validators.required, Validators.minLength(ANY_NUMBER > 1)]);
And in template:
<div *ngIf="emailsCtrl.invalid">
<span *ngIf="emailsCtrl.hasError('required')">
It's required
</span>
<span *ngIf="emailsCtrl.hasError('minlength')">
It should have at least {{emailsCtrl.getError('minlength').requiredLength}} emails
</span>
</div>
PS2:
I think makes more sense to pass the index of the email that you want to delete in your removeEmail
function, so you willn't have to call indexOf
to get the index of the specific email
. You can do something like this:
<div *ngFor="let emailInfo of emailsCtrl.value; let i = index">
{{emailInfo.email}}
<button (click)="removeEmail(i)">
Remove
</button>
</div>
Component:
removeEmail(i: number): void {
this.emailsCtrl.removeAt(i);
}
Take a look at this simple DEMO
Solution 2:
This works for me (angular 2.1.2), this approach gives you the flexibility to define a custom validation for your emails:
this.profileForm = this.formBuilder.group({
emails: [this.profile.emails, FormValidatorUtils.nonEmpty]
// ......
});
export class FormValidatorUtils {
static nonEmpty(control: any) {
if (!control.value || control.value.length === 0) {
return { 'noElements': true };
}
return null;
}
}
Post a Comment for "How To Assign And Validate Arrays To Forms In Angular2"