Memvalidasi formulir terhadap standar dengan API Validasi

Pada suatu waktu, hampir semua orang menyukai Angular 2+, ini adalah kerangka kerja yang dirancang dengan baik yang berada di atas kerangka kerja front-end populer lainnya dalam hal kinerja teknik. Tetapi dia juga memiliki kekurangan yang sangat aneh. Salah satunya adalah ketidakmungkinan memanggil validasi atau validasi ulang formulir secara manual, yang diamati setidaknya hingga versi ke-8. Ini bukan untuk mengatakan bahwa mereka sangat menyukai reaktivitas, tetapi dalam subsistem ini, tampaknya beberapa pertimbangan reaktif mendorong pengembang untuk menerapkan validasi hanya melalui pengikatan, memaksa pengembang aplikasi untuk beralih ke kruk seperti menyetel status "tak tersentuh" โ€‹โ€‹untuk bidang dan umumnya mempersulit penulisan validator kompleks dengan lanjutan logika dan partisipasi dari beberapa bidang sekaligus.Pengalaman saya dengan Angular validator dan beberapa fitur lain dari kerangka kerja memperkuat kesan saya tentang betapa elegan dan sederhana setelah itu menggunakan API HTML5 untuk validasi formulir, yang "hanya berfungsi" di browser modern apa pun, bahkan tanpa kerangka kerja dan perpustakaan.



Atribut elemen adalah dasar untuk validator. Dengan menggunakan atribut, kita dapat langsung mengatur batasan berikut:

wajib diisi - bidang wajib diisi, mis. memerlukan pengisian

min max step - minimum dan maximum allowable values, serta langkah mengubah

minlength dan maxlength - pembatas jumlah

pola karakter masukan yang diizinkan - ekspresi reguler

Tampaknya tidak banyak, namun pola memberi kita peluang yang cukup kaya untuk memeriksa nilai, pelanggan tetap biasa mudah dicari di Google memungkinkan untuk segera memeriksa nomor telepon, alamat email dan URL dan banyak lagi yang dibutuhkan.

Diatur pada elemen formulir, atribut ini tidak akan secara otomatis memungkinkan tombol dipicu dari formulir yang sama yang melakukan nilai kirim ke server, meskipun saat ini kasus seperti itu mungkin tampak anakronistik bagi banyak orang. Tapi ini bukan masalah, karena dengan JavaScript sisi klien, kita dapat menggunakan semua validator ini dengan cara yang sama atau bahkan lebih baik. Oleh karena itu, kami tidak akan menggunakan input type = email, tetapi mencoba membuat bidang kami sendiri dengan memeriksa input untuk kepatuhan dengan aturan untuk menghasilkan alamat email. Mari buat formulir sederhana:

<form name="myform" id="myform">
   <input type="text" pattern="^[a-zA-Z0-9.!#$%&โ€™*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" placeholder="email here"/>
   <input type="submit">
</form>


Validator segera bekerja dan setelah mencoba menekan tombol, ia mengeluarkan peringatan dalam bahasa lokal browser.







Karenanya, memasukkan mail@example.com akan menghasilkan pengiriman formulir yang berhasil.

Untuk mengembangkan perilaku Anda, Anda perlu mengakses contoh formulir, ini dapat dilakukan melalui dokumen global dengan nama, indeks (id) atau ordinal mulai dari nol.

<script type="module">
   document.forms.myform.onsubmit = (event) => {
       console.log('validate');
       return false;
   };
</script>


atau oleh pemilih menggunakan salah satu metode, seperti document.getElementById () atau document.querySelector (),

untuk memeriksa hasilnya, jalankan http-server

npx http-server


setelah perintah dijalankan, Anda dapat membuka 127.0.0.1 : 8080 / atau alamat yang ditulisnya kepada Anda di konsol di browser dan men-debug hasilnya.



Mari kita ganti kirim dengan tombol biasa dan panggil validasi formulir secara manual, sedikit mengubah contoh.

<form id="myform" action="#">
   <input type="text" pattern="^[a-zA-Z0-9.!#$%&โ€™*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" required placeholder="email here" />
   <input type="button" name="subm" value="OK" />
</form>

<script type="module">;
   myform.subm.onclick = (event) => {
       console.log(form.checkValidity());
       return false;
   };
</script>


Dalam contoh ini, Anda dapat melihat bahwa memetakan objek formulir dengan id dan namanya berfungsi untuk elemen anak dalam kaitannya dengan formulir, yang terlihat sangat elegan. Sekarang kode kami mencetak status validitas formulir ke konsol.

Adanya metode untuk meluncurkan validasi secara manual tidak berarti bahwa itu tidak dapat dilakukan tanpa memanggilnya.

Hasil masukan dan perubahan lain ke formulir segera tercermin dalam statusnya, yang dimanifestasikan dengan adanya kelas-semu dari gaya yang valid dan tidak valid . Jika Anda menambahkan sorotan warna, maka Anda dapat melihat bagaimana validasi langsung bekerja.

<style>
  :valid {
       border: 1px solid green;
   }
  :invalid {
       border: 1px solid red;
   }
</style>








Untuk mencegah formulir mengganggu mata dengan warna merah sebelum pengguna mencoba memasukkan sesuatu ke dalamnya, Anda dapat menggunakan life hack dengan placeholder:

<style>
   input:valid {
       border: 1px solid green;
   }
   input:not(:placeholder-shown):invalid {
       border: 1px solid red;
   }
</style>


Penangan eksternal untuk peristiwa validasi dapat digantung pada elemen formulir.

<script type="module">
   myform.email.oninvalid = (event) => {
       alert('Wrong email !!11');
   };
   myform.subm.onclick = (event) => {
       console.log(form.checkValidity());
       return false;
   };
</script>


Dalam hal ini, mekanisme hook digunakan dengan nama event, jika ada beberapa event yang didukung oleh elemen tersebut, maka dengan menugaskan sebuah fungsi bernama on + <event_name> padanya, kita bisa yakin bahwa itu akan dipanggil ketika diaktifkan.



Dan satu hal lagi yang luar biasa di sini adalah bahwa mereka tidak akan lagi dipanggil ketika data dimasukkan, tetapi hanya ketika validasi secara terprogram, yaitu. memanggil metode checkValidity ().



Karenanya, kami dapat menangani perilaku ini:

myform.subm.onclick = (event) => {
   if (myform.checkValidity()) {
       alert('Valid !');
   } else {
       alert('Invalid !')
   }
   return false;
};


Dalam kehidupan nyata, kita mungkin juga perlu memanggil event.preventDefault () jika validasi gagal membatalkan prosedur pengiriman formulir.



Pada checkValidity () adalah analog reportValidity () , yang mengembalikan hasil tanpa menyebabkan validasi ulang.



Bagaimana Anda tahu bidang mana yang salah?



Setiap elemen masukan formulir memiliki properti .validity, serta kemampuan untuk memanggil metode validasi di atasnya, properti tersebut memiliki struktur berikut:



ValueState: {

valid - tanda umum dari kebenaran

valueMissing - nilai diperlukan, tetapi tidak disetel

typeMismatch - tipe yang salah

dimasukkan patternMismatch - diperkenalkan nilai yang tidak cocok

tooLong - nilai lebih besar dari maxlength

tooShort - nilai kurang dari minlength

rangeUnderflow - nilai kurang dari min

rangeOverflow - nilai lebih besar dari max

stepMismatch - nilai tidak cocok dengan langkah

badInput - input tidak dapat

dipaksa untuk nilai customError - arbitrary error

}



Pada dasarnya, seperti yang bisa kita lihat, properti kesalahan yang sesuai dengan atribut validasi standar, sedangkan .customError adalah ruang utama kami untuk ekstensi. Dengan

memanggil metode .setCustomValidity () dengan string kesalahan sebagai argumen, kita bisa menandai elemen formulir sebagai tidak valid. Anda juga dapat menyetel atau mendapatkan teks kesalahan melalui properti .validationMessage...

Agar tidak menyetel validasi browser, Anda dapat menggunakan properti .willValidate , yang menunjukkan apakah validasi standar akan dipanggil di lapangan.

Dengan meneruskan string kosong sebagai argumen ke .setCustomValidity () kita bisa mengembalikan statusnya ke valid.

Mari tambahkan dukungan untuk atribut pola-saya kita sendiri , yang akan memeriksa nilai terhadap ekspresi reguler dengan cara yang sama untuk kejelasan.

Jika terjadi kesalahan, pesan, selain yang disediakan di browser, akan ditampilkan di sebelah kolom.

Validasi akan dipicu saat nilai kolom alternatif kami berubah dan saat tombol ditekan.

<form id="myform" action="#">
   <div>
       <input type="text" name="email" id="email" value="" pattern="^[a-zA-Z0-9.!#$%&โ€™*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" required placeholder="email here" />
       <span class="msg"></span>
   </div>
   <div>
       <input type="text" name="customInput" id="customInput" my-pattern="^[a-zA-Z0-9.!#$%&โ€™*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" required placeholder="text here" />
       <span class="msg"></span>
   </div>
   <button type="submit" name="subm" value="OK">OK</button>
</form>
<style>
   input:valid {
       border: 1px solid green;
   }
   input:not(:placeholder-shown):invalid {
       border: 1px solid red;
   }
</style>
<script type="module">
   myform.customInput.oninvalid = (event) => {
       let el = event.target;
       let msg = el.parentElement.querySelector('.msg');
       msg.innerText = el.validationMessage;
       console.log('oninvalid, id: ', el.id);
   };
   myform.customInput.oninput = (event) => {
       let el = event.currentTarget;
       validateWithMyPattern(el);
       markValidity(el);
   };
   function markValidity(el) {
       el.checkValidity();
       let msg = el.parentElement.querySelector('.msg');
       if (el.validity.valid) {
           msg.innerText = '';
       } else {
           msg.innerText = el.validationMessage;
       }
   }
   function validateWithMyPattern(field) {
       if (field.value) {
           if (field.hasAttribute('my-pattern') &&
               field.value.match(field.getAttribute('my-pattern'))) {
               field.setCustomValidity('');
           } else {
               field.setCustomValidity('My pattern error');
           }
       }
   }
   myform.subm.onclick = (event) => {
       for (let formEl of myform.querySelectorAll('input')) {
           validateWithMyPattern(formEl);
           markValidity(formEl);
       }
       if (myform.reportValidity()) {
           alert('Valid !');
       } else {
           alert('Invalid !')
       }
       return false;
   };
</script>


Sekarang kami memiliki dua bidang serupa yang memeriksa nilai dengan validator standar dan satu lagi yang telah kami tulis sendiri.







Kemungkinannya mungkin tidak tampak kaya, namun, dengan bantuannya Anda dapat menerapkan validasi apa pun, termasuk. kelompok bidang tanpa tersandung pada batasan teknis seperti pada kerangka kerja populer.



Dari batasan Validation API, saya hanya ingat validasi awal bidang. Untuk itu, selain trik dengan placeholder atau status khusus a-la tak tersentuh, Anda dapat melakukan semua validasi secara terprogram pada masukan dan acara pengiriman dengan menggabungkan validator Anda sendiri dengan yang standar.

Memecahkan masalah saya, saya sampai pada kebutuhan untuk membuat komponen saya sendiri yang melakukan tugas formulir pada saat yang sama untuk mendukung elemen masukan saya sendiri, yang memungkinkan Anda untuk mengatur validasi berbeda dan perilaku pemberitahuan dan menggantung validator apa pun dan menggunakan API Validasi standar. Anda dapat melihatnya di sini: https://bitbucket.org/techminded/skinny-widgets/src/master/src/form/

dan contoh kode dari artikel ini dapat ditemukan di sini:

https://bitbucket.org/techminded/myform /



All Articles