what nativeelement example elementref directives typescript angular

typescript - nativeelement - Angular 2 validadores mĂșltiples



elementref nativeelement (3)

¿Es posible tener validadores múltiples en un campo de formulario? Intenté esto, pero resultó en algunos errores extraños (el campo nunca fue válido, incluso si se cumplieron los requisitos)

this.username = new Control('''', Validators.minLength(5), Validators.required);

¿Cómo puedo usar validadores múltiples?


Puede combinar validadores usando Validators.compose()

this.username = new Control('''', Validators.compose( [Validators.minLength(5), Validators.required]));

para uso de validadores asíncronos

this.username = new Control('''', null, Validators.composeAsync( [someAsyncValidator, otherAsyncValidator]));

Hay problemas abiertos con los validadores asíncronos, especialmente los validadores de sincronización combinados con los validadores asíncronos no funcionan

Para hacer que los validadores de sincronización funcionen con los validadores asíncronos, envuelva los validadores de sincronización con promesas y compóngalos como validadores asíncronos como

this.username = new Control('''', null, Validators.composeAsync([ (control:Control) => Promise.resolve(Validators.minLength(5)(control)), (control:Control) => Promise.resolve(Validators.required(control)), someAsyncValidator, otherAsyncValidator ]));


Sugiero utilizar el método Validators.compose () para combinar todos los validadores no asíncronos y pasar por separado el Validators.composeAsync () para cualquier llamada asíncrona.

Básicamente, los argumentos del constructor para FormControl son los siguientes:

  1. formState (o simplemente el valor inicial inicial)
  2. validadores (sugiero usar Validators.compose ([...]) aquí)
  3. asyncValidators (sugiero usar Validators.composeAsync ([...]) aquí

Ejemplo utilizando FormBuilder (siéntase libre de usar el control directo):

this.acctForm = this.fb.group({ ''name'': [ '''', Validators.compose([ Validators.required, Validators.minLength(2), Validators.maxLength(20), Validators.pattern(''[a-zA-Z]'') ]) ], ''cellNumber'': [ '''', Validators.compose([ Validators.required, Validators.pattern(''[0-9]{10}'') ]), Validators.composeAsync([ this.checkPhoneValid.bind(this) ]) ] });

Esto ayuda a evitar la validación asíncrona hasta que los validadores no asíncronos sean válidos (excl. La verificación inicial, que se puede manejar fácilmente, ver más abajo).

Todo ejemplo combinado (validadores, asyncValidators y debouncing):

import { Component, Injectable, OnInit } from ''@angular/core''; import { Http } from ''@angular/http''; import { FormBuilder, FormGroup, Validators, AbstractControl } from ''@angular/forms''; @Component({ selector: ''app-sandbox'', templateUrl: ''./sandbox.component.html'', providers: [] }) export class FormControlsDemoComponent implements OnInit { private debouncedTimeout; public acctForm: FormGroup; constructor(private http: Http, private fb: FormBuilder) { // @note Http should never be directly injected into a component, for simplified demo sake... } ngOnInit() { this.acctForm = this.fb.group({ // Simple Example with Multiple Validators (non-async) ''name'': [ '''', Validators.compose([ Validators.required, Validators.minLength(2), Validators.maxLength(20), Validators.pattern(''[a-zA-Z]'') ]) ], // Example which utilizes both Standard Validators with an Async Validator ''cellNumber'': [ '''', Validators.compose([ Validators.required, Validators.minLength(4), Validators.maxLength(15), Validators.pattern(''[0-9]{10}'') ]), Validators.composeAsync([ this.checkPhoneValid.bind(this) // Important to bind ''this'' (otherwise local member context is lost) /* @note if using a service method, it would look something like this... @example: this.myValidatorService.phoneUniq.bind(this.myValidatorService) */ ]) ], // Example with both, but Async is implicitly Debounced ''userName'': [ '''', Validators.compose([ Validators.required, Validators.minLength(4), Validators.maxLength(15), Validators.pattern(''[a-zA-Z0-9_-]'') ]), Validators.composeAsync([ this.checkUserUniq.bind(this) // @see above async validator notes regarding use of bind ]) ] }); } /** * Demo AsyncValidator Method * @note - This should be in a service */ private checkPhoneValid(control: AbstractControl): Promise<any> { // Avoids initial check against an empty string if (!control.value.length) { Promise.resolve(null); } const q = new Promise((resolve, reject) => { // determine result from an http response or something... let result = true; if (result) { resolve(null); } else { resolve({''phoneValidCheck'': false}); } }); return q; } /** * Demo AsyncValidator Method (Debounced) * @note - This should be in a service */ private checkUserUniq(control: AbstractControl): Promise<any> { // Avoids initial check against an empty string if (!control.value.length) { Promise.resolve(null); } clearTimeout(this.debouncedTimeout); const q = new Promise((resolve, reject) => { this.debouncedTimeout = setTimeout(() => { const req = this.http .post(''/some/endpoint'', { check: control.value }) .map(res => { // some handler logic... return res; }); req.subscribe(isUniq => { if (isUniq) { resolve(null); } else { resolve({''usernameUnique'': false }); } }); }, 300); }); return q; } }

A algunas personas les gusta piratear en el validador asíncrono rebotado vinculando los cambios de valores observables del control de esta manera:

this.someControl.debounceTime(300).subscribe(val => { // async call... });

Personalmente no lo recomiendo para la mayoría de los casos, ya que agrega complicaciones innecesarias.

NOTA: Esto debería funcionar a partir de la última versión de Angular (2 y 4) desde la redacción de esta publicación.


este problema ha sido abordado

puedes hacer una serie de validadores

this.username = new FormControl('''', [ Validators.minLength(5), Validators.required ]);