angular angular-reactive-forms angular-validation

Validador angular 4 para verificar 2 controles al mismo tiempo



angular-reactive-forms angular-validation (2)

Tengo una forma reactiva con 2 controles (port_start y port_end) que tienen los siguientes requisitos:

  • Ambos deben tener un valor
  • Sus valores deben estar entre 0 y 65535
  • el valor de port_start debe ser menor que el valor de port_end

Esto es lo que intenté hasta ahora:

[...] this.formModel.addControl(''port_start'', new FormControl(object.port_start ? object.port_start : 0, [Validators.required, Validators.min(0), Validators.max(65535), this.minMaxValidator(''port_start'', ''port_end'').bind(this)])); this.formModel.addControl(''port_end'', new FormControl(object.ort_end ? object.port_end : 0, [Validators.required, Validators.min(0), Validators.max(65535), this.minMaxValidator(''port_start'', ''port_end'').bind(this)])); [...]

Esta es la función de validación personalizada:

minMaxValidator = function(startControl : string, endControl : string): ValidatorFn { return (control: FormControl): {[key: string]: any} => { let valid = true; let valStart = 0; let valEnd = 0; if(this.formModel.controls[startControl] && this.formModel.controls[endControl]) { valStart = <number>this.formModel.controls[startControl].value; valEnd = <number>this.formModel.controls[endControl].value; } valid = valEnd >= valStart; return valid ? null : { minmax : true }; }; }

Esto funciona bien, excepto por este problema:

  • Digamos que escribo ''2'' en el campo ''port_start''. Angular lo marca como no válido porque es más que el valor de ''port_end'' (que es 0 por defecto). Si escribo ''5'' en el campo ''port_end'', la aplicación aún muestra ''port_start'' como no válido, aunque ahora es correcto.

Entiendo que el problema es que necesito volver a verificar el campo asociado cada vez que cambio el valor del otro, pero no sé cómo hacerlo.

¿Algunas ideas? Gracias,


A diferencia de @Tomasz dijo, puede mantener la validación en el nivel de control.

El secreto: escuche los cambios en su formulario y, cuando ocurra, configure los validadores con los valores actuales.

Aquí hay un stackblitz que te muestra cómo funciona.

Y aquí está el código que usé:

import { Component } from ''@angular/core''; import { FormBuilder, FormGroup, ValidatorFn, AbstractControl } from ''@angular/forms''; @Component({ selector: ''my-app'', template: ` <form [formGroup]="form"> <input type="number" formControlName="start"> <input type="number" formControlName="end"> </form> <div *ngIf="form.get(''start'').hasError(''lessThan'')">Min should be less than max</div> <div *ngIf="form.get(''end'').hasError(''moreThan'')">Max should be less than min</div> `, styleUrls: [''./app.component.css''] }) export class AppComponent { form: FormGroup; constructor(private fb: FormBuilder) { this.form = fb.group({ start: [0], end: [65535] }); this.form.valueChanges.subscribe(changes => { this.form.get(''start'').setValidators(LessThanEnd(+this.form.value.end)); this.form.get(''end'').setValidators(MoreThanStart(+this.form.value.start)); }); } } export function LessThanEnd(end: number): ValidatorFn { return (control: AbstractControl): { [key: string]: any } => { return control.value > end ? { ''lessThan'': true } : null; }; } export function MoreThanStart(end: number): ValidatorFn { return (control: AbstractControl): { [key: string]: any } => { return control.value < end ? { ''moreThan'': true } : null; }; }


Los validadores max , max y required pueden mantenerse tal cual. Si desea validar un control en función del valor de otro, debe elevar la validación al control principal.

import { Component } from ''@angular/core''; import { ValidatorFn, FormBuilder, FormGroup, Validators } from ''@angular/forms''; const portStartEnd: ValidatorFn = (fg: FormGroup) => { const start = fg.get(''portStart'').value; const end = fg.get(''portEnd'').value; return start && end && start < end ? null : { startEnd: true }; } @Component({ selector: ''my-app'', template: ` <input [formControl]="form.get(''portStart'')" type="number" > <input [formControl]="form.get(''portEnd'')" type="number" > {{ form.valid }} `, styleUrls: [''./app.component.css''] }) export class AppComponent { form: FormGroup; constructor(private fb: FormBuilder) { this.form = this.fb.group({ portStart: [null, [Validators.required, Validators.min(0), Validators.max(65535)]], portEnd: [null, [Validators.required, Validators.min(0), Validators.max(65535)]] }, { validator: portStartEnd } ); } }

Demo en vivo