If you want to go the route of model driven forms, here's a sample for that. BUT if you have a simple form, using model driven forms might be overkill. But, if you have a complex form, this would be a good option.
Here I have form:
<form [formGroup]="myForm">
<button (click)="addCustomer()">Add Customer</button>
<div formArrayName="customers">
<div *ngFor="let cust of myForm.controls.customers.controls; let i = index" >
<div formGroupName="{{i}}">
<p>Customer {{i+1}}</p>
<label>E-mail</label>
<input formControlName="email" />
<span *ngIf="!myForm.controls.customers.controls[i].controls.email.valid">Required!</span>
</div>
<hr>
</div>
</div>
<button type="submit">Submit</button>
</form>
But if you have many several different validations for one and the same form control, I would go ahead and use the latter suggestion by mickdev, where you can capture changes and do check the validations and display the correct validation message. E.g, check first that user has entered an email, and after that check if the email is a valid e-mail etc. But if you just have a couple of form validations you can of course check those errors directly in the template. This is a pretty good link, explaining reactive forms and the validations, basically what I have presented here in code.
Here would be the TS file to above form, where customers would be an formarray where you can push new formcontrols:
this.myForm = this.fb.group({
customers: this.fb.array([
this.initCustomers()
])
});
initCustomers() {
return this.fb.group({
email: ['', Validators.required]
})
}
addCustomer() {
const control = <FormArray>this.myForm.controls['customers'];
control.push(this.initCustomers())
}
Here's a demo plunker with the above code