Tengo validación tanto en el frontend como en el backend. Todo está bien con una interfaz, pero no puedo trabajar con la validación de back-end en la interfaz (marcar manualmente los controles como no válidos en función de la validación de back-end).
El problema está en completar los controles de formulario con errores, parece que no puedo simplemente hacer this.formBuiltWithFormBuilder.setErrors() y pasar un objeto con errores para completar automáticamente todos los controles incluidos en un formulario, ya que solo el formulario se vuelve inválido cuando todos los estados de campo permanecen mismo.
Así que actualmente estoy tratando de hacer algo como:
// Example of incoming formErrors: // (it can also be nested for nested forms) // { // phone: { // phoneNumberNoMatch: "The input does not match..." // } // } @Input() public formErrors: ValidationErrors; public detailsForm: FormGroup; public ngOnInit() { this.createForm(); } public ngOnChanges() { this.updateFormErrors(this.formErrors); } private createForm(account: AccountInterface) { this.detailsForm = this.fb.group({ firstName: ['', Validators.required], lastName: ['', Validators.required] }); } private updateFormErrors(errors: any) { if (this.detailsForm) { // Trying to populate included form controls with errors this.detailsForm.setErrors(errors); } }```
También pensé en recorrer el objeto de errores y aplicar errores manualmente para cada control, pero creo que esta solución no es la ideal, ya que puede haber formularios anidados.
Entonces, ¿es una forma de completar automáticamente los controles de formulario con errores?
Parece que no hay una solución integrada, por lo que he creado una clase auxiliar de formulario para completar los errores. En teoría, también debería llenar formularios anidados/matriz, pero lo he probado solo para formularios simples. Avísame si no es así ;)
Utiliza el método lodash/map para recorrer el objeto de errores.
import { FormGroup, FormControl, FormArray } from '@angular/forms'; import { map } from 'lodash'; export class FormHelper { public static POPULATE_FORM_GROUP_ERRORS( rootFormGroup: FormGroup, errors: any ) { map(rootFormGroup.controls, (control, name) => { if (control instanceof FormControl) { if (errors.hasOwnProperty(name)) { control.setErrors(errors[name]); } } if (control instanceof FormGroup) { if (errors.hasOwnProperty(name)) { FormHelper.POPULATE_FORM_GROUP_ERRORS(control, errors[name]); } } if (control instanceof FormArray) { if (errors.hasOwnProperty(name) && errors[name] instanceof Array) { this.iterateOverFormArrayControl(control, errors[name]); } } }); } private static iterateOverFormArrayControl( formArray: FormArray, errors: any[] ) { errors.forEach((error: any, index: number) => { const arrayControl = formArray.at(index); if (arrayControl && arrayControl instanceof FormControl) { arrayControl.setErrors(error); } if (arrayControl && arrayControl instanceof FormGroup) { FormHelper.POPULATE_FORM_GROUP_ERRORS(arrayControl, error); } if (arrayControl && arrayControl instanceof FormArray && error instanceof Array) { FormHelper.iterateOverFormArrayControl(arrayControl, error); } }); } }Así que ahora mi formulario se ve así:
// ... Somewhere at the top import { FormHelper } from '@app/commons/FormHelper'; // ... // Example of incoming formErrors: // (it can also be nested for nested forms) // { // phone: { // phoneNumberNoMatch: "The input does not match..." // } // } @Input() public formErrors: ValidationErrors; public detailsForm: FormGroup; public ngOnInit() { this.createForm(); } public ngOnChanges() { this.updateFormErrors(this.formErrors); } private createForm(account: AccountInterface) { this.detailsForm = this.fb.group({ firstName: ['', Validators.required], lastName: ['', Validators.required] }); } private updateFormErrors(errors: any) { if (this.detailsForm) { // Populate included form controls with errors FormHelper.POPULATE_FORM_GROUP_ERRORS(this.detailsForm, errors); } }