es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Angular FormControl personalizado con updateOn blur

Tengo un formulario reactivo que funciona perfectamente con updateOn submit y updateOn change.

Pero cuando cambio a updateOn blur, se activa el error requerido directamente después de ingresar un carácter en mi control de formulario personalizado y nunca desaparece. Además, cuando envío mi formulario, todos los valores de mis controles de formulario personalizados están vacíos (aunque los campos estén completos).

Mi formulario TS:

activityForm = this.fb.group({
placeName: [”, { validators: [Validators.required, Validators.maxLength(75)] }],
description: [”, { validators: [Validators.required, Validators.minLength(25), Validators.maxLength(2000)] }],
}, { updateOn: ‘blur’ })

Mi formulario HTML:

{{‘poi.place_name’ | transloco}}



{{‘poi.description’ | transloco}}




Custom FormControl TS (el de textarea):

export class CustomTextareaComponent implements ControlValueAccessor {

@Input() placeholder = ” // give a transloco string directly
@Input() limit = 500
@Input() error: boolean = false

value: string | null = null
currentNumberOfCharacters: number = 0
isActive: boolean | undefined

onChange: any = () => { }
onTouch: any = () => { }
touched = false
disabled = false

changes(event: Event) {
if (this.disabled) return
this.markAsTouched()
this.value = event?.target ? (event?.target as HTMLTextAreaElement).value : ”
this.currentNumberOfCharacters = this.value.length
this.onChange(this.value)
}

/* Methods needed by ControlValueAccessor to transform this component into a “form friendly” component */

registerOnChange(providedFunction: any) {
this.onChange = providedFunction
}

registerOnTouched(providedFunction: any) {
this.onTouch = providedFunction
}

writeValue(providedValue: any) {
if (providedValue) {
this.value = providedValue
this.currentNumberOfCharacters = providedValue.length
}
}

setDisabledState(providedDisabledVal: any) {
this.disabled = providedDisabledVal
}

markAsTouched() {
if (!this.touched) {
this.onTouch()
this.touched = true
}
}

}

Custom FormControl HTML (el de textarea):

{{ currentNumberOfCharacters }}/{{ limit }} {{ ‘common.characters’ | transloco }}

Entonces mi pregunta es: ¿Cómo hago para que updateOn blur funcione con un FormControl personalizado?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El problema parece ser que el error requerido se activa directamente después de ingresar un carácter en el control de formulario personalizado y nunca desaparece. Esto se debe a que el control de formulario se marca como “tocado” inmediatamente después de ingresar un carácter, incluso si el usuario aún no ha salido del campo.

    Para solucionar este problema, puede utilizar una combinación de eventos (blur) e (input).

    Así es como puede modificar el método changes() en CustomTextareaComponent:

    changes(event: Event) {
      if (this.disabled) return
    
      this.value = (event?.target as HTMLTextAreaElement).value
      this.currentNumberOfCharacters = this.value.length
      this.onChange(this.value)
      this.isActive = !!this.value
    
      // Verificar si hay errores de validación
      const errors = this.validator(this.value)
    
      // Si no hay errores, marcar el control como prístino
      if (!errors) {
        this.markAsPristine()
      }
    
      // Si el control está activo, no marcar como tocado
      if (this.isActive) {
        return
      }
    
      // Marcar control como tocado
      this.markAsTouched()
    }
    

    Hemos agregado un método validator() que verifica cualquier error de validación. Este método debe devolver el objeto de error si hay errores de validación y null si no hay errores.

    También hemos agregado un método markAsPristine() para marcar el control como prístino si no hay errores de validación. Esto es necesario porque markAsTouched() también marcará el control como sucio, lo cual no es lo que queremos.

    Por último, vérifiquemos si el control está activo (es decir, el usuario está escribiendo actualmente en el control) y no lo marque como tocado si lo está.

    Así es como puede modificar su plantilla para usar los eventos (blur) e (input):

    <textarea [placeholder]="placeholder | transloco" [value]="value" (input)="changes($event)" (blur)="changes($event)" [maxlength]="limit" class="plnd-textarea__field"></textarea>
    

    Ahora estamos utilizando tanto los eventos (input) como (blur) para llamar al método changes(). El evento (input) se activará cada vez que el usuario escriba o elimine caracteres en el control. El evento (blur) se activará cuando el control pierda el enfoque.

Comments are closed.