Estoy tratando de crear un formulario donde el usuario pueda seleccionar varios colores y luego enviar el formulario.
Código
colors: Array<any> = [ { description: 'White', value: 'White' }, { description: 'Black', value: 'Black' }, { description: 'Blue', value: 'Blue' }, { description: 'Green', value: 'Green' }, { description: 'Yellow', value: 'Yellow' }, { description: 'Red', value: 'Red' }, ]; constructor( private formBuilder: FormBuilder ) { this.fromInit(); } ngOnInit(): void {} fromInit() { this.form = this.formBuilder.group({ colors: this.formBuilder.array([], [Validators.required]), }); } onCheckChange(event) { const formArray: FormArray = this.form.get( 'colors' ) as FormArray; if (event.target.checked) { formArray.push(new FormControl(event.target.value)); } else { let i: number = 0; formArray.controls.forEach((ctrl: FormControl) => { if (ctrl.value == event.target.value) { formArray.removeAt(i); return; } i++; }); } } invalidColorsMessage() { if (this.form.controls['colors'].errors?.required) return "You must choose a color"; }HTML
<div class="invalid-input-message" *ngIf="this.form.controls['colors'].touched && this.form.controls['colors'].invalid"> {{invalidColorsMessage()}}</div>El problema que encontré con esa propiedad 'tocada' de this.form.controls['colors'] siempre es falso. no importa si selecciono algunas casillas de verificación o no selecciono nada, el valor de 'tocado' siempre es falso.
Realmente no entiendo por qué siempre es falso cuando marco y desmarco las casillas de verificación.
el resultado esperado es mostrar un mensaje de error cada vez que alguien marca y desmarca las casillas y deja todo vacío.
Me gustaría saber por qué el valor de this.form.controls['colors'].touched siempre es falso, pase lo que pase. Así que traté de buscar la respuesta en línea, pero desafortunadamente no tuve éxito en encontrar la solución.
Aquí hay una demostración de las casillas de verificación: https://stackblitz.com/edit/angular-ivy-s8rc6j?file=src/app/app.component.html
Gracias
Actualizar stackblitz :
set isTouched = false; a la variable global
marque *ngIf=="isTouched && this.form.controls['colors'].invalid"
agregó this.isTouched = true; en onCheckChange(event) {}
Este es un problema cerrado de Github
La propiedad touch refleja si un control de formulario se ha desenfocado, no cambiado.
El formulario tocado nunca volvería verdadero porque el evento borroso solo ocurrió en el elemento de entrada.
Puede cambiar su código de:
<div class="invalid-input-message" *ngIf="this.form.controls['colors'].touched && this.form.controls['colors'].invalid"> Para: (eliminar this.form.controls['colors'].touched condition)
<div class="invalid-input-message" *ngIf="this.form.controls['colors'].invalid">Podrías usar un validador personalizado, ¡qué bueno que es reutilizable! Lo adjuntamos a la matriz y verificamos la longitud de la matriz, si la longitud es al menos 1 , markAllAsTocuhed , por lo tanto, puede mantener su touched en la plantilla. Entonces la función se vería así:
export function validate(ctrls: FormArray): ValidationErrors | null { if (ctrls.value.length) { ctrls.markAllAsTouched(); return null; } return { notValid: true }; }Puede poner esto en un servicio o en algún lugar donde otros componentes puedan importarlo si desea que sea reutilizable.
Bien, ahora adjuntemos esto a la matriz de formas:
fromInit() { this.form = this.formBuilder.group({ colors: this.formBuilder.array([], { validators: validate }), }); }Y luego, en la plantilla, verifica si existe un error y si está tocado:
<div *ngIf="form.get('colors').hasError('notValid') && form.get('colors').touched"> Please choose at least one </div>Tu STACKBLITZ bifurcado