Cómo activar validadores de formulario en Angular2

82

En angular2 quiero activar Validadores para algunos controles cuando se cambia otro control. ¿Hay alguna forma de que pueda decirle al formulario que se vuelva a validar? Mejor aún, ¿puedo solicitar la validación de campos específicos?

Ejemplo: Dada la casilla de verificación X y la entrada P. La entrada P tiene un validador que se comporta de manera diferente en función del valor del modelo de X.Cuando X está marcado / desmarcado, necesito invocar el validador en P. El validador en P mirará el modelo para determinará el estado de X y validará P en consecuencia.

Aquí hay un código:

constructor(builder: FormBuilder) {
    this.formData = { num: '', checkbox: false };

    this.formGp = builder.group({
        numberFld: [this.formData.num, myValidators.numericRange],
        checkboxFld: [this.formData.checkbox],
    });
}

this.formGp.controls['checkboxFld'].valueChanges.observer({
    next: (value) => {
        // I want to be able to do something like the following line:
        this.formGp.controls['numberFld'].validator(this.formGp.controls['numberFld']);
    }
});

¿Alguien tiene una solución? ¡Gracias!

Bonneville
fuente
¿Está intentando habilitar / deshabilitar la validación en función del valor de X? ¿Qué tipo de validadores estás usando? Puede hacer que los validadores se ejecuten en función de una condición en su alcance, pero no estoy seguro de si ese enfoque funcionará para usted. Ver: stackoverflow.com/questions/21370006/…
stephen.vakil
@ stephen.vakil - Estoy usando angular2.
Bonneville
@Bonneville, ¿podría explicar cómo está pasando el estado de la casilla de verificación a la función de validación?
Varun Mulloli

Respuestas:

79

No sé si todavía está buscando una respuesta, así que aquí están mis sugerencias:

Eche un vistazo a esto: Angular 2 - AbstractControl

Creo que lo que podrías hacer es seguir:

this.formGp.controls['checkboxFld'].valueChanges.observer({
    next: (value) => {
       this.formGp.controls['numberFld'].updateValueAndValidity();
    }
});

Esto debería activar y ejecutar los validadores. Además, el estado también se actualiza. Ahora debería poder consultar el valor de la casilla de verificación dentro de la lógica de su validador.

¡Espero que esto ayude!

EDITAR: enlace actualizado y ejemplo. El código cambió mientras escribía mi respuesta.

EDIT_2: alpha.48 cambia EventEmitter.observer a EventEmitter.subscribe!

EDIT_3: enlace modificado a la implementación real, enlace agregado a los documentos

Guía de validación

Documentación de FormControl

Nightking
fuente
Gracias @Nightking por la sugerencia, la probaré. Tenga en cuenta que su enlace no funciona.
Bonneville
@Bonneville Gracias por la información. Extrajeron el código del formulario al espacio de nombres común. Las cosas cambian un poco a rápido :). Actualicé el enlace a la fuente.
Nightking
Finalmente pude usar este código y parece que me está funcionando. ¡Gracias! Por cierto, hay un error tipográfico en su código: falta la letra 'e' en la función updateValueAndValidity (). Tu código tiene actualización en lugar de actualización. ¡Salud, esto fue de gran ayuda!
Bonneville
1
El enlace está roto; puede actualizarse a github.com/angular/angular/blob/master/packages/forms/src/… aunque no es exactamente lo mismo. También se puede vincular a documentos angulares
píldoras de explosión
1
Salvavidas !! El caso de uso en el que me quedé atascado fue cuando el usuario envía un formulario sin tocar un solo control de formulario. El formulario no es válido, pero los controles no muestran ningún mensaje de error
pravin
42

con mi ControlGroup hago esto porque tengo errores divs al verificar si se tocan

for (var i in this.form.controls) {
  this.form.controls[i].markAsTouched();
}

(this.form es mi ControlGroup)

kernowcode
fuente
esta es realmente la respuesta correcta. Si desea una sola entrada this.form.controls ['nombre']. MarkAsTouched ();
chris_r
19

Con la ayuda de este blog

enlace del blog

Me encontré con una solución con la combinación de la respuesta de Nightking

Object.keys(this.orderForm.controls).forEach(field => {
       const control = this.orderForm.get(field);
       control.updateValueAndValidity();

});

this.orderForm es el grupo de formularios

Altair CA
fuente
8

Esto hizo el truco para mi

this.myForm.markAllAsTouched();
C.Ikongo
fuente
6

Hay formas más elegantes de modelar este comportamiento, por ejemplo, poner su estado en un ReplaySubject y observarlo, y luego usar validadores asíncronos que observan el estado, pero el enfoque pseudocodificado a continuación debería funcionar. Simplemente observe los cambios de valor en la casilla de verificación, actualice el modelo según corresponda, luego fuerce una revalidación de numberFld con la calibración updateValueAndValidity.

constructor(builder: FormBuilder) {
  this.formData = { num: '', checkbox: false };
  const numberFld = builder.control(this.formData.num, myValidators.numericRange);

  const checkbox = builder.control(this.formData.checkbox);
  checkbox.valueChanges.map(mapToBoolean).subscribe((bool) => {
    this.formData.checked = bool;
    numberFld.updateValueAndValidity(); //triggers numberFld validation
  });

  this.formGp = builder.group({
      numberFld: numberFld,
      checkboxFld: checkbox
  });
}
jmreidy
fuente
0
static minMaxRange(min: number, max: number): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
        if (Validators.min(min)(control)) { // if min not valid
            return Validators.min(min)(control);
        } else {
            return Validators.max(max)(control);
        }
    };
}
pogiaron
fuente