Reputation: 45
I have this form using Angular 2:
<form [formGroup]="form">
<div formArrayName="passageiros">
<div *ngFor="let passageiro of form.get('passageiros')['controls']; let i=index">
<div [formGroupName]="i">
<div class="row">
<div class="col-md-2">
<h3><strong ngDefaultControl>{{ModPassageiros[i].NomeTipoPassageiro}} {{i + 1}}:</strong></h3>
</div>
<div class="col-md-2">
<mat-input-container style="width: 100%">
<input matInput [matDatepicker]="picker" placeholder="Data Nasc" [max]="maxDataNasc" formControlName="DataNascimento" name="DataNascimento" [(ngModel)]="ModPassageiros[i].DataNascimento" (dateInput)="pegaIndice($event, i)" (dateChange)="pegaIndice($event, i)" required>
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker ></mat-datepicker>
<mat-error *ngIf="!form.controls.passageiros.controls[i].controls.DataNascimento.valid && !form.controls.passageiros.controls[i].controls.DataNascimento.pristine " >
Insira uma data de nascimento válida e de acordo com o tipo de pessoa (Adulto, criança ou bebê).
</mat-error>
</mat-input-container>
</div>
</div>
</div>
</div>
</div>
</form>
I want to validate the birth date according passenger type value.
This is the Type Script:
constructor(private fb:FormBuilder) {
this.form = this.fb.group({
passageiros: this.fb.array([
this.iniciaPassageiros(),
]),
}
)
}
iniciaPassageiros() {
return this.fb.group({
DataNascimento :[new Date(), Validators.compose([
Validators.required,
(control) => this.validarDataNascPorTipo(control, this.indicePassageiros)
])]
});
}
public pegaIndice(e, i)
{
this.indicePassageiros = i;
}
And this is the custom validator function:
public validarDataNascPorTipo(control : AbstractControl, i)
{
let dias : number = this.util.calcularDias(control.value);
if(this.ModPassageiros[i])
{
if(this.ModPassageiros[i].Tipo == 'ADT' && dias < 4015)
return {"Data nascimento não é de " : true
if(this.Tipo == 'INF' && dias > 700)
return { "Data nascimento não é de ' + this.schemaJson.Metadados.Modelos.ModPassageiros[i].Tipo + '(abaixo de 23 meses)." : true }
if(this.ModPassageiros[i].Tipo == 'CHD' && (dias > 4014 || dias < 700))
return { "Data nascimento não é de ' + this.schemaJson.Metadados.Modelos.ModPassageiros[i].Tipo + '(acima 23 meses e até de 11 anos)." : true};
}
return null;
}
I´m trying to pass the actual index to validate the right control but angular is calling the custom validation function before (change) envent. For this, the validation don´t have the behavior expected. How can I solve this problem? Is there a way to pass the index of form array by control? Or, to call the validation function always after cheange event?
Upvotes: 1
Views: 177
Reputation: 99
Form validation with Angular couples the validation with the component.
This leads to the business logic around validation being scattered all over the application in components.
Many times it is better to create a TypeScript based re-usable validation service.
This allows the business logic to be centralized in one place.
You can unit test this business logic by unit testing the service.
This demo Angular 6 CLI app shows you how to do this.
https://github.com/VeritasSoftware/ts-validator-app-angular6
You might find this useful from your design considerations.
Upvotes: 1
Reputation: 57909
As the only thing you want is the index you can get it using parent
iniciaPassageiros() {
return this.fb.group({
DataNascimento :[new Date(), [Validators.required,this.customValidator]
});
}
customValidator(control) {
if (control) {
let fbgroup = control.parent; //<--the FormGroup
if (fbgroup) {
let fbarray=fbgroup.parent; //<--the FormArray
let index=fbarray.controls.indexOf(fbgroup);
}
}
Upvotes: 0