Estandarizar el comportamiento de las formas en el proyecto (Angular)



Para crear una interfaz f谩cil de usar, debe asegurarse de que todos los formularios de su aplicaci贸n se comporten de manera coherente. El comportamiento mon贸tono a menudo se logra mediante c贸digo repetitivo, aunque impl铆citamente. Perm铆tanme compartirles un boceto de un patr贸n que creo que simplifica el desarrollo y estandariza el comportamiento de las formas.



Si el c贸digo para enviar formularios en su proyecto es similar a este, le aconsejo que busque en cat.



onSubmit (): void
// login.component.ts
// bad practices
onSubmit(): void {
  this.formSubmitted = true;
  this.isUnhandledServerError = false;
  if (!this.formGroup.valid) return;
  this.isLoading = true;
  const { username, password } = this.formGroup.value;
  this.login(username, password)
    .pipe(finalize(() => (this.isLoading = false)))
    .subscribe({ error: error => this.handleError(error) });
}




Para aquellos que simplemente aman el c贸digo:

proyecte en stackblitz antes de refactorizar.

Proyecto Stackblitz despu茅s de la refactorizaci贸n.



Descripci贸n del problema



Los formularios requieren muchos matices para ser tenidos en cuenta. Desde un punto de vista funcional, el formulario simplemente env铆a la informaci贸n ingresada por el usuario al servidor. Pero para asegurar una UX de alta calidad, adem谩s de todo, hay que hacer validaciones, mostrar errores del servidor, un indicador de carga, etc. En la pr谩ctica, los desarrolladores a menudo pasan por alto estos detalles, lo que afecta negativamente la usabilidad de la aplicaci贸n o da como resultado la duplicaci贸n de c贸digo y hace que el desarrollo de formularios sea una rutina intolerable.



Aqu铆 hay un ejemplo de un controlador de env铆o de formularios que es bueno desde el punto de vista de UX, pero malo desde el punto de vista del desarrollo. Proyecto Stackblitz antes de la refactorizaci贸n.



// login.component.ts
onSubmit(): void {
  this.formSubmitted = true; //   
  this.isUnhandledServerError = false; //       
  if (!this.formGroup.valid) return; //  
  this.isLoading = true; //   
  const { username, password } = this.formGroup.value;
  this.login(username, password) //    
    .pipe(finalize(() => (this.isLoading = false))) //   
    .subscribe({ error: error => this.handleError(error) });
}


Como puede ver, este controlador tiene en cuenta muchos de los detalles que componen la UX. El 煤nico problema es que con este enfoque, estos matices deber谩n escribirse para cada formulario de la aplicaci贸n.



Decisi贸n



Para simplificar el desarrollo y estandarizar el comportamiento de los formularios en su aplicaci贸n, debe mover el c贸digo del controlador de env铆o de formularios a una clase separada. Proyecto Stackblitz despu茅s de la refactorizaci贸n. (Simplifiqu茅 intencionalmente el c贸digo para el ejemplo, en un proyecto real debe reemplazar todos los campos booleanos con Observable).



class Form<T> {
    submitted = false;

    pending = false;

    hasUnhandledServerError = false;

    constructor(private formGroup: FormGroup, private action: (value: any) => Observable<T>) {}

    submit(): Observable<T> {
        if (this.pending) return EMPTY;
        this.submitted = true;
        this.hasUnhandledServerError = false;
        if (this.formGroup.valid) {
            this.pending = true;
            return this.action(this.formGroup.value).pipe(
                tap({ error: () => (this.hasUnhandledServerError = true) }),
                finalize(() => (this.pending = false)),
            );
        }
        return EMPTY;
    }
}


Por lo tanto, concentramos la mayor铆a de las caracter铆sticas de UX en una clase y nos deshacemos de la l贸gica duplicada. Ahora, escribir un nuevo formulario llevar谩 menos tiempo y puede completar el comportamiento de los formularios en toda la aplicaci贸n cambiando solo la clase Form.



驴Por qu茅 no ponerlo en la biblioteca?



Los requisitos de UX para cada proyecto son 煤nicos y dependen m谩s del dise帽ador. Ya he tenido que redefinir el comportamiento de los elementos est谩ndar de Material a petici贸n del cliente. Por lo tanto, no veo ninguna forma de estandarizar el comportamiento de los formularios en todas las aplicaciones usando una biblioteca. Deje que el comportamiento de la interfaz quede a merced del dise帽ador y los desarrolladores. Sin embargo, creo que es una buena idea separar la l贸gica relacionada con UX en clases separadas.



Espero que el ejemplo haya sido 煤til y que intente utilizar la idea en sus proyectos. 隆Mientras!



All Articles