Standarisasi perilaku formulir dalam proyek (Angular)



Untuk membuat antarmuka yang ramah pengguna, Anda harus memastikan bahwa semua formulir dalam aplikasi Anda berperilaku secara konsisten. Perilaku monoton seringkali dicapai dengan kode berulang, meskipun secara implisit. Izinkan saya membagikan sketsa pola yang menurut saya menyederhanakan pengembangan dan membakukan perilaku formulir.



Jika kode untuk mengirimkan formulir dalam proyek Anda mirip dengan yang ini, saya menyarankan Anda untuk melihat di bawah 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) });
}




Bagi mereka yang menyukai kode:

Proyek di stackblitz sebelum melakukan refactoring.

Proyek Stackblitz setelah refactoring.



Deskripsi masalah



Formulir membutuhkan banyak nuansa untuk dipertimbangkan. Dari sudut pandang fungsional, formulir hanya mengirimkan informasi yang dimasukkan oleh pengguna ke server. Tetapi untuk memastikan UX berkualitas tinggi, selain semuanya, Anda harus melakukan validasi, menampilkan kesalahan dari server, indikator pemuatan, dll. Dalam praktiknya, detail ini sering diabaikan oleh developer, yang berdampak negatif pada kegunaan aplikasi, atau mengakibatkan duplikasi kode dan membuat pengembangan formulir menjadi rutinitas yang tidak dapat ditoleransi.



Berikut adalah contoh penangan pengiriman formulir yang baik dari sudut pandang UX, tetapi buruk dari sudut pandang pengembangan. Proyek Stackblitz sebelum refactoring.



// 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) });
}


Seperti yang Anda lihat, penangan ini memperhitungkan banyak detail yang membentuk UX. Satu-satunya masalah adalah dengan pendekatan ini, nuansa ini harus dituliskan untuk setiap formulir dalam aplikasi.



Keputusan



Untuk menyederhanakan pengembangan dan menstandarisasi perilaku formulir dalam aplikasi Anda, Anda perlu memindahkan kode penangan pengiriman formulir ke kelas terpisah. Proyek Stackblitz setelah refactoring. (Saya sengaja menyederhanakan kode sebagai contoh; dalam proyek nyata, Anda perlu mengganti semua bidang boolean dengan 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;
    }
}


Jadi, kami memusatkan sebagian besar fitur UX dalam satu kelas dan menghilangkan logika duplikat. Sekarang menulis formulir baru akan memakan waktu lebih sedikit, dan Anda dapat menyelesaikan perilaku formulir di seluruh aplikasi dengan hanya mengubah kelas Formulir.



Mengapa tidak menaruhnya di perpustakaan?



Persyaratan UX untuk setiap proyek unik dan lebih bergantung pada perancangnya. Saya sudah harus mendefinisikan ulang perilaku elemen Material standar atas permintaan pelanggan. Oleh karena itu, saya tidak melihat cara apa pun untuk menstandarisasi perilaku formulir di semua aplikasi menggunakan satu perpustakaan. Biarkan perilaku antarmuka tetap bergantung pada perancang dan pengembang. Namun, menurut saya, sebaiknya pisahkan logika terkait UX ke dalam kelas yang terpisah.



Saya harap contoh ini bermanfaat dan Anda akan mencoba menggunakan ide tersebut dalam proyek Anda. Sementara!



All Articles