Cara menggunakan javascript checkvalidity

Banyak pengguna hari ini berharap. Bagaimana Anda mencapai tingkat interaktivitas ini ketika Anda membangun situs statis kecil atau aplikasi Rails atau Laravel yang dirender server? . js dan Yodium. js adalah dua perpustakaan JavaScript minimal yang dapat kita gunakan untuk membuat formulir yang sangat interaktif dengan sedikit hutang teknis dan sedikit waktu pemuatan halaman kita. Pustaka seperti ini mencegah Anda dari keharusan menggunakan alat JavaScript berat langkah-bangun yang dapat memperumit arsitektur Anda

Saya akan mengulangi beberapa versi validasi formulir untuk menjelaskan API dari kedua pustaka ini. Jika Anda ingin menyalin dan menempelkan produk jadi, inilah yang akan kami buat. Cobalah bermain-main dengan input yang hilang atau tidak valid dan lihat bagaimana form bereaksi

CodePen Embed Fallback

Sekilas tentang perpustakaan

Sebelum kita benar-benar mendalaminya, ada baiknya kita berkenalan dengan perkakas yang kita gunakan

Alpine dirancang untuk ditarik ke proyek Anda dari CDN. Tidak ada langkah build, tidak ada konfigurasi bundler, dan tidak ada dependensi. Itu hanya membutuhkan GitHub pendek

<input name="email" type="email" id="email" data-rules='["required","email"]'>
2 untuk dokumentasinya. Hanya jam 8. 36 kilobyte diperkecil dan di-gzip, kira-kira seperlima dari ukuran hello world aplikasi-buat-reaksi. Hugo Di Francesco menawarkan ikhtisar lengkap dan menyeluruh tentang apa itu dan bagaimana cara kerjanya. Deskripsi awalnya tentang itu cukup bagus

Alpen. js adalah pengganti rasa template Vue untuk jQuery dan vanilla JavaScript daripada pesaing React/Vue/Svelte/WhateverFramework

Yodium, di sisi lain, adalah pustaka validasi bentuk mikro, dibuat oleh Matt Kingshott yang bekerja di dunia Laravel/Vue/Tailwind. Yodium dapat digunakan dengan kerangka kerja front-end apa pun sebagai pembantu validasi formulir. Ini memungkinkan kami untuk memvalidasi satu bagian data dengan beberapa aturan. Yodium juga mengembalikan pesan kesalahan yang masuk akal saat validasi gagal. Anda dapat membaca lebih lanjut di postingan blog Matt yang menjelaskan alasan di balik Yodium

Sekilas tentang bagaimana Yodium bekerja

Inilah validasi formulir sisi klien yang sangat mendasar menggunakan Iodine. Kami akan menulis beberapa vanilla JavaScript untuk didengarkan saat formulir dikirimkan, lalu gunakan metode DOM untuk memetakan input untuk memeriksa setiap nilai input. Jika salah, kami akan menambahkan kelas "tidak valid" ke input yang tidak valid dan mencegah pengiriman formulir

Kami akan menarik Yodium dari tautan CDN ini untuk contoh ini

<script src="https://cdn.jsdelivr.net/gh/mattkingshott/[email protected]/dist/iodine.min.js" defer></script>
_

Atau kita bisa mengimpornya ke proyek dengan Skypack

import kingshottIodine from "https://cdn.skypack.dev/@kingshott/iodine";

Kita perlu mengimpor

<input name="email" type="email" id="email" data-rules='["required","email"]'>
_3 saat mengimpor Yodium dari Skypack. Ini masih menambahkan
<input name="email" type="email" id="email" data-rules='["required","email"]'>
4 ke cakupan global/jendela kita. Dalam kode pengguna Anda, Anda dapat terus merujuk ke perpustakaan sebagai
<input name="email" type="email" id="email" data-rules='["required","email"]'>
4, tetapi pastikan untuk mengimpor
<input name="email" type="email" id="email" data-rules='["required","email"]'>
3 jika Anda mengambilnya dari Skypack

Untuk memeriksa setiap masukan, kami memanggil metode

<input name="email" type="email" id="email" data-rules='["required","email"]'>
7 pada Iodine. Kami meneruskan nilai input sebagai parameter pertama, dan array string sebagai parameter kedua. String ini adalah aturan yang harus diikuti input agar valid. Daftar aturan bawaan dapat ditemukan di dokumentasi Yodium

Metode

<input name="email" type="email" id="email" data-rules='["required","email"]'>
7 Iodine mengembalikan
<input name="email" type="email" id="email" data-rules='["required","email"]'>
9 jika nilainya valid, atau string yang menunjukkan aturan gagal jika pemeriksaan gagal. Ini berarti kita harus menggunakan perbandingan ketat saat bereaksi terhadap keluaran fungsi; . Apa yang bisa kita lakukan adalah menyimpan array string untuk aturan untuk setiap input sebagai JSON dalam atribut data HTML. Ini tidak dibangun di Alpine atau Iodine, tapi menurut saya ini cara yang bagus untuk menempatkan input bersama dengan batasannya. Perhatikan bahwa jika Anda melakukan ini, Anda harus mengapit JSON dengan tanda kutip tunggal dan menggunakan tanda kutip ganda di dalam atribut untuk mengikuti spesifikasi JSON

Begini tampilannya di HTML kita

<input name="email" type="email" id="email" data-rules='["required","email"]'>

Saat kami memetakan melalui DOM untuk memeriksa validitas setiap input, kami memanggil fungsi

<input name="email" type="email" id="email" data-rules='["required","email"]'>
4 dengan nilai input elemen, lalu
let form = document.getElementById("form");

// This is a nice way of getting a list of checkable input elements
// And converting them into an array so we can use map/filter/reduce functions:
let inputs = [...form.querySelectorAll("input[data-rules]")];

function onSubmit(event) {
  inputs.map((input) => {
    if (Iodine.is(input.value, JSON.parse(input.dataset.rules)) !== true) {
      event.preventDefault();
      input.classList.add("invalid");
    }
  });
}
form.addEventListener("submit", onSubmit);
2 hasil dari
let form = document.getElementById("form");

// This is a nice way of getting a list of checkable input elements
// And converting them into an array so we can use map/filter/reduce functions:
let inputs = [...form.querySelectorAll("input[data-rules]")];

function onSubmit(event) {
  inputs.map((input) => {
    if (Iodine.is(input.value, JSON.parse(input.dataset.rules)) !== true) {
      event.preventDefault();
      input.classList.add("invalid");
    }
  });
}
form.addEventListener("submit", onSubmit);
3 input. Seperti inilah tampilannya menggunakan metode vanilla JavaScript DOM

let form = document.getElementById("form");

// This is a nice way of getting a list of checkable input elements
// And converting them into an array so we can use map/filter/reduce functions:
let inputs = [...form.querySelectorAll("input[data-rules]")];

function onSubmit(event) {
  inputs.map((input) => {
    if (Iodine.is(input.value, JSON.parse(input.dataset.rules)) !== true) {
      event.preventDefault();
      input.classList.add("invalid");
    }
  });
}
form.addEventListener("submit", onSubmit);

Inilah implementasi yang sangat mendasar ini

CodePen Embed Fallback

Seperti yang Anda tahu, ini bukan pengalaman pengguna yang hebat. Yang terpenting, kami tidak memberi tahu pengguna apa yang salah dengan pengiriman tersebut. Pengguna juga harus menunggu hingga formulir dikirimkan sebelum menemukan ada yang salah. Dan yang membuat frustrasi, semua input mempertahankan kelas "tidak valid" bahkan setelah pengguna memperbaikinya untuk mengikuti aturan validasi kami

Di sinilah Alpine berperan

Mari tarik dan gunakan untuk memberikan umpan balik pengguna yang bagus saat berinteraksi dengan formulir

Opsi yang baik untuk validasi formulir adalah memvalidasi input saat diburamkan atau pada perubahan apa pun setelah diburamkan. Hal ini memastikan bahwa kita tidak meneriaki pengguna sebelum mereka selesai menulis, tetapi tetap memberi mereka umpan balik instan jika mereka meninggalkan input yang tidak valid atau kembali dan mengoreksi nilai input

Kami akan menarik Alpine dari CDN

<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js" defer></script>

Atau kita bisa mengimpornya ke proyek dengan Skypack

import alpinejs from "https://cdn.skypack.dev/alpinejs";

Sekarang hanya ada dua keadaan yang perlu kita tahan untuk setiap masukan

  • Apakah input telah kabur
  • Pesan kesalahan (tidak adanya ini berarti kami memiliki input yang valid)

Validasi yang kami tunjukkan dalam formulir akan menjadi fungsi dari dua bagian negara ini

Alpine memungkinkan kita mempertahankan status ini dalam komponen dengan mendeklarasikan objek JavaScript biasa dalam atribut

let form = document.getElementById("form");

// This is a nice way of getting a list of checkable input elements
// And converting them into an array so we can use map/filter/reduce functions:
let inputs = [...form.querySelectorAll("input[data-rules]")];

function onSubmit(event) {
  inputs.map((input) => {
    if (Iodine.is(input.value, JSON.parse(input.dataset.rules)) !== true) {
      event.preventDefault();
      input.classList.add("invalid");
    }
  });
}
form.addEventListener("submit", onSubmit);
4 pada elemen induk. Status ini dapat diakses dan dimutasi oleh elemen turunannya untuk menciptakan interaktivitas. Untuk menjaga kebersihan HTML, kita dapat mendeklarasikan fungsi JavaScript yang mengembalikan semua data dan/atau fungsi yang dibutuhkan formulir. Kemudian kita hanya perlu mendaftarkan fungsi kita dengan Alpine menggunakan atribut
let form = document.getElementById("form");

// This is a nice way of getting a list of checkable input elements
// And converting them into an array so we can use map/filter/reduce functions:
let inputs = [...form.querySelectorAll("input[data-rules]")];

function onSubmit(event) {
  inputs.map((input) => {
    if (Iodine.is(input.value, JSON.parse(input.dataset.rules)) !== true) {
      event.preventDefault();
      input.classList.add("invalid");
    }
  });
}
form.addEventListener("submit", onSubmit);
5, dan memanggil
let form = document.getElementById("form");

// This is a nice way of getting a list of checkable input elements
// And converting them into an array so we can use map/filter/reduce functions:
let inputs = [...form.querySelectorAll("input[data-rules]")];

function onSubmit(event) {
  inputs.map((input) => {
    if (Iodine.is(input.value, JSON.parse(input.dataset.rules)) !== true) {
      event.preventDefault();
      input.classList.add("invalid");
    }
  });
}
form.addEventListener("submit", onSubmit);
6 setelah mendaftarkannya. Menggunakan Alpine dengan cara ini juga menyediakan cara yang dapat digunakan kembali untuk berbagi logika karena kita dapat menggunakan fungsi yang sama di beberapa komponen atau bahkan beberapa proyek

Mari menginisialisasi formulir data untuk menampung objek untuk setiap kolom input dengan dua properti. string kosong untuk

let form = document.getElementById("form");

// This is a nice way of getting a list of checkable input elements
// And converting them into an array so we can use map/filter/reduce functions:
let inputs = [...form.querySelectorAll("input[data-rules]")];

function onSubmit(event) {
  inputs.map((input) => {
    if (Iodine.is(input.value, JSON.parse(input.dataset.rules)) !== true) {
      event.preventDefault();
      input.classList.add("invalid");
    }
  });
}
form.addEventListener("submit", onSubmit);
_7 dan boolean disebut kabur. Kami akan menggunakan atribut nama dari setiap elemen sebagai kuncinya


<form id="form" x-data="form" action="">
  <h1>Log In</h1>

  <label for="username">Username</label>
  <input name="username" id="username" type="text" data-rules='["required"]'>

  <label for="email">Email</label>
  <input name="email" type="email" id="email" data-rules='["required","email"]'>

  <label for="password">Password</label>
  <input name="password" type="password" id="password" data-rules='["required","minimum:8"]'>

  <label for="passwordConf">Confirm Password</label>
  <input name="passwordConf" type="password" id="passwordConf" data-rules='["required","minimum:8"]'>

  <input type="submit">
</form>

Dan inilah fungsi kita untuk mengatur data. Perhatikan bahwa kuncinya cocok dengan atribut

let form = document.getElementById("form");

// This is a nice way of getting a list of checkable input elements
// And converting them into an array so we can use map/filter/reduce functions:
let inputs = [...form.querySelectorAll("input[data-rules]")];

function onSubmit(event) {
  inputs.map((input) => {
    if (Iodine.is(input.value, JSON.parse(input.dataset.rules)) !== true) {
      event.preventDefault();
      input.classList.add("invalid");
    }
  });
}
form.addEventListener("submit", onSubmit);
_8 dari input kita


Alpine.data("form", form);
Alpine.start();
function form(){ 
  return {
    username: {errorMessage:'', blurred:false},
    email: {errorMessage:'', blurred:false},
    password: {errorMessage:'', blurred:false},
    passwordConf: {errorMessage:'', blurred:false},
  }
}

Sekarang kita dapat menggunakan atribut

let form = document.getElementById("form");

// This is a nice way of getting a list of checkable input elements
// And converting them into an array so we can use map/filter/reduce functions:
let inputs = [...form.querySelectorAll("input[data-rules]")];

function onSubmit(event) {
  inputs.map((input) => {
    if (Iodine.is(input.value, JSON.parse(input.dataset.rules)) !== true) {
      event.preventDefault();
      input.classList.add("invalid");
    }
  });
}
form.addEventListener("submit", onSubmit);
9 Alpine pada input kita untuk menambahkan kelas "invalid" jika input kabur dan ada pesan untuk elemen dalam data komponen kita. Begini tampilannya di input nama pengguna kami

<input name="username" id="username" type="text" 
x-bind:class="{'invalid':username.errorMessage && username.blurred}" data-rules='["required"]'>

Menanggapi perubahan masukan

Sekarang kita membutuhkan formulir kita untuk merespons perubahan input dan status input yang kabur. Kita dapat melakukan ini dengan menambahkan event listener. Alpine memberikan API ringkas untuk melakukan ini baik menggunakan

<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js" defer></script>
0 atau, mirip dengan Vue, kita dapat menggunakan simbol
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js" defer></script>
1. Kedua cara mendeklarasikan tindakan ini dengan cara yang sama

Pada event input kita perlu mengubah

let form = document.getElementById("form");

// This is a nice way of getting a list of checkable input elements
// And converting them into an array so we can use map/filter/reduce functions:
let inputs = [...form.querySelectorAll("input[data-rules]")];

function onSubmit(event) {
  inputs.map((input) => {
    if (Iodine.is(input.value, JSON.parse(input.dataset.rules)) !== true) {
      event.preventDefault();
      input.classList.add("invalid");
    }
  });
}
form.addEventListener("submit", onSubmit);
7 dalam data komponen menjadi pesan error jika nilainya tidak valid;

Pada acara

<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js" defer></script>
_3 kita perlu menyetel properti
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js" defer></script>
4 sebagai
<input name="email" type="email" id="email" data-rules='["required","email"]'>
9 pada objek dengan kunci yang cocok dengan nama elemen buram. Kami juga perlu menghitung ulang pesan kesalahan untuk memastikan tidak menggunakan string kosong yang kami inisialisasi sebagai pesan kesalahan

Jadi kita akan menambahkan dua fungsi lagi ke formulir kita untuk bereaksi terhadap pemburaman dan memasukkan perubahan, dan menggunakan nilai

let form = document.getElementById("form");

// This is a nice way of getting a list of checkable input elements
// And converting them into an array so we can use map/filter/reduce functions:
let inputs = [...form.querySelectorAll("input[data-rules]")];

function onSubmit(event) {
  inputs.map((input) => {
    if (Iodine.is(input.value, JSON.parse(input.dataset.rules)) !== true) {
      event.preventDefault();
      input.classList.add("invalid");
    }
  });
}
form.addEventListener("submit", onSubmit);
8 dari target acara untuk menemukan bagian mana dari data komponen kita yang akan diubah. Kita dapat mendeklarasikan fungsi ini sebagai properti dalam objek yang dikembalikan oleh fungsi
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js" defer></script>
7

Inilah HTML kami untuk input nama pengguna dengan event listener terlampir

<input 
  name="username" id="username" type="text"
  x-bind:class="{'invalid':username.errorMessage && username.blurred}" 
  @blur="blur" @input="input"
  data-rules='["required"]'
>

Dan JavaScript kami dengan fungsi yang merespons pendengar acara

import kingshottIodine from "https://cdn.skypack.dev/@kingshott/iodine";
0

Mendapatkan dan menampilkan kesalahan

Selanjutnya, kita perlu menulis fungsi ________16______8 kita

Jika cek Yodium mengembalikan

<input name="email" type="email" id="email" data-rules='["required","email"]'>
_9, kami akan menyetel properti
let form = document.getElementById("form");

// This is a nice way of getting a list of checkable input elements
// And converting them into an array so we can use map/filter/reduce functions:
let inputs = [...form.querySelectorAll("input[data-rules]")];

function onSubmit(event) {
  inputs.map((input) => {
    if (Iodine.is(input.value, JSON.parse(input.dataset.rules)) !== true) {
      event.preventDefault();
      input.classList.add("invalid");
    }
  });
}
form.addEventListener("submit", onSubmit);
7 ke string kosong. Jika tidak, kami akan meneruskan aturan yang telah dilanggar ke metode Iodine lain.
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js" defer></script>
_8. Ini akan mengembalikan pesan yang dapat dibaca manusia. Begini tampilannya

import kingshottIodine from "https://cdn.skypack.dev/@kingshott/iodine";
1

Sekarang kita juga perlu menunjukkan pesan kesalahan kita kepada pengguna

Mari tambahkan tag

import alpinejs from "https://cdn.skypack.dev/alpinejs";
_2 dengan kelas
import alpinejs from "https://cdn.skypack.dev/alpinejs";
3 di bawah setiap masukan. Kita dapat menggunakan atribut Alpine lain yang disebut
import alpinejs from "https://cdn.skypack.dev/alpinejs";
4 pada elemen ini untuk hanya menampilkannya ketika pesan kesalahannya ada. Atribut
import alpinejs from "https://cdn.skypack.dev/alpinejs";
_4 menyebabkan Alpine untuk beralih
import alpinejs from "https://cdn.skypack.dev/alpinejs";
6 pada elemen berdasarkan apakah ekspresi JavaScript memutuskan untuk
<input name="email" type="email" id="email" data-rules='["required","email"]'>
9. Kita dapat menggunakan ekspresi yang sama dengan yang kita gunakan di kelas
import alpinejs from "https://cdn.skypack.dev/alpinejs";
8 pada input

Untuk menampilkan teks, kita dapat menghubungkan pesan kesalahan kita dengan

import alpinejs from "https://cdn.skypack.dev/alpinejs";
9. Ini akan secara otomatis mengikat

<form id="form" x-data="form" action="">
  <h1>Log In</h1>

  <label for="username">Username</label>
  <input name="username" id="username" type="text" data-rules='["required"]'>

  <label for="email">Email</label>
  <input name="email" type="email" id="email" data-rules='["required","email"]'>

  <label for="password">Password</label>
  <input name="password" type="password" id="password" data-rules='["required","minimum:8"]'>

  <label for="passwordConf">Confirm Password</label>
  <input name="passwordConf" type="password" id="passwordConf" data-rules='["required","minimum:8"]'>

  <input type="submit">
</form>
_0 ke ekspresi JavaScript tempat kita dapat menggunakan status komponen kita. Begini tampilannya

import kingshottIodine from "https://cdn.skypack.dev/@kingshott/iodine";
2

Satu hal terakhir yang dapat kita lakukan adalah menggunakan kembali kode


<form id="form" x-data="form" action="">
  <h1>Log In</h1>

  <label for="username">Username</label>
  <input name="username" id="username" type="text" data-rules='["required"]'>

  <label for="email">Email</label>
  <input name="email" type="email" id="email" data-rules='["required","email"]'>

  <label for="password">Password</label>
  <input name="password" type="password" id="password" data-rules='["required","minimum:8"]'>

  <label for="passwordConf">Confirm Password</label>
  <input name="passwordConf" type="password" id="passwordConf" data-rules='["required","minimum:8"]'>

  <input type="submit">
</form>
1 sebelum kita menarik Alpine, tetapi kali ini kita dapat menambahkan event listener ke elemen form dengan

<form id="form" x-data="form" action="">
  <h1>Log In</h1>

  <label for="username">Username</label>
  <input name="username" id="username" type="text" data-rules='["required"]'>

  <label for="email">Email</label>
  <input name="email" type="email" id="email" data-rules='["required","email"]'>

  <label for="password">Password</label>
  <input name="password" type="password" id="password" data-rules='["required","minimum:8"]'>

  <label for="passwordConf">Confirm Password</label>
  <input name="passwordConf" type="password" id="passwordConf" data-rules='["required","minimum:8"]'>

  <input type="submit">
</form>
2 dan menggunakan fungsi

<form id="form" x-data="form" action="">
  <h1>Log In</h1>

  <label for="username">Username</label>
  <input name="username" id="username" type="text" data-rules='["required"]'>

  <label for="email">Email</label>
  <input name="email" type="email" id="email" data-rules='["required","email"]'>

  <label for="password">Password</label>
  <input name="password" type="password" id="password" data-rules='["required","minimum:8"]'>

  <label for="passwordConf">Confirm Password</label>
  <input name="passwordConf" type="password" id="passwordConf" data-rules='["required","minimum:8"]'>

  <input type="submit">
</form>
3 di data komponen kita. Alpine memungkinkan kita menggunakan

<form id="form" x-data="form" action="">
  <h1>Log In</h1>

  <label for="username">Username</label>
  <input name="username" id="username" type="text" data-rules='["required"]'>

  <label for="email">Email</label>
  <input name="email" type="email" id="email" data-rules='["required","email"]'>

  <label for="password">Password</label>
  <input name="password" type="password" id="password" data-rules='["required","minimum:8"]'>

  <label for="passwordConf">Confirm Password</label>
  <input name="passwordConf" type="password" id="passwordConf" data-rules='["required","minimum:8"]'>

  <input type="submit">
</form>
_4 untuk merujuk ke elemen induk yang menyimpan status komponen kita. Ini berarti kita tidak perlu menulis lagi metode DOM

import kingshottIodine from "https://cdn.skypack.dev/@kingshott/iodine";
3
import kingshottIodine from "https://cdn.skypack.dev/@kingshott/iodine";
4

CodePen Embed Fallback

Ini menuju ke sana

  • Kami memiliki umpan balik waktu nyata saat masukan diperbaiki
  • Formulir kami memberi tahu pengguna tentang masalah apa pun sebelum mereka mengirimkan formulir, dan hanya setelah mereka mengaburkan input
  • Formulir kami tidak dikirimkan jika ada properti yang tidak valid

Memvalidasi di sisi klien dari aplikasi yang dirender di sisi server

Masih ada beberapa masalah dengan versi ini, meskipun beberapa tidak akan langsung terlihat jelas di Pena karena terkait dengan server. Misalnya, sulit memvalidasi semua error di sisi klien dalam aplikasi yang dirender di sisi server. Bagaimana jika alamat email sudah digunakan? . Ada beberapa cara untuk melakukannya dengan AJAX, tetapi kami akan melihat solusi yang lebih ringan

Kami dapat menyimpan kesalahan sisi server di atribut data array JSON lain pada setiap input. Sebagian besar kerangka kerja back-end akan menyediakan cara yang cukup mudah untuk melakukan ini. Kita dapat menggunakan atribut Alpine lain yang disebut


<form id="form" x-data="form" action="">
  <h1>Log In</h1>

  <label for="username">Username</label>
  <input name="username" id="username" type="text" data-rules='["required"]'>

  <label for="email">Email</label>
  <input name="email" type="email" id="email" data-rules='["required","email"]'>

  <label for="password">Password</label>
  <input name="password" type="password" id="password" data-rules='["required","minimum:8"]'>

  <label for="passwordConf">Confirm Password</label>
  <input name="passwordConf" type="password" id="passwordConf" data-rules='["required","minimum:8"]'>

  <input type="submit">
</form>
5 untuk menjalankan fungsi saat komponen diinisialisasi. Dalam fungsi ini kita dapat menarik kesalahan sisi server dari DOM ke dalam setiap data komponen masukan. Kemudian kita dapat memperbarui fungsi
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js" defer></script>
_8 untuk memeriksa apakah ada kesalahan server dan mengembalikannya terlebih dahulu. Jika tidak ada, maka kami dapat memeriksa kesalahan sisi klien

import kingshottIodine from "https://cdn.skypack.dev/@kingshott/iodine";
5

Dan untuk memastikan kesalahan sisi server tidak muncul sepanjang waktu, bahkan setelah pengguna mulai memperbaikinya, kami akan menggantinya dengan larik kosong setiap kali masukannya diubah

Inilah fungsi init kita sekarang

import kingshottIodine from "https://cdn.skypack.dev/@kingshott/iodine";
6

Menangani input yang saling bergantung

Beberapa input formulir mungkin bergantung pada yang lain untuk validitasnya. Misalnya, input konfirmasi kata sandi akan bergantung pada kata sandi yang dikonfirmasi. Atau tanggal Anda memulai bidang pekerjaan harus memiliki nilai lebih lama dari bidang tanggal lahir Anda. Artinya, sebaiknya periksa semua input formulir setiap kali input diubah

Kita dapat memetakan semua elemen input dan mengatur statusnya pada setiap input dan peristiwa blur. Dengan cara ini, kita tahu bahwa input yang saling bergantung tidak akan menggunakan data lama

Untuk mengujinya, mari tambahkan aturan


<form id="form" x-data="form" action="">
  <h1>Log In</h1>

  <label for="username">Username</label>
  <input name="username" id="username" type="text" data-rules='["required"]'>

  <label for="email">Email</label>
  <input name="email" type="email" id="email" data-rules='["required","email"]'>

  <label for="password">Password</label>
  <input name="password" type="password" id="password" data-rules='["required","minimum:8"]'>

  <label for="passwordConf">Confirm Password</label>
  <input name="passwordConf" type="password" id="passwordConf" data-rules='["required","minimum:8"]'>

  <input type="submit">
</form>
7 untuk konfirmasi kata sandi kita. Yodium memungkinkan kita menambahkan aturan khusus baru dengan metode

<form id="form" x-data="form" action="">
  <h1>Log In</h1>

  <label for="username">Username</label>
  <input name="username" id="username" type="text" data-rules='["required"]'>

  <label for="email">Email</label>
  <input name="email" type="email" id="email" data-rules='["required","email"]'>

  <label for="password">Password</label>
  <input name="password" type="password" id="password" data-rules='["required","minimum:8"]'>

  <label for="passwordConf">Confirm Password</label>
  <input name="passwordConf" type="password" id="passwordConf" data-rules='["required","minimum:8"]'>

  <input type="submit">
</form>
8

import kingshottIodine from "https://cdn.skypack.dev/@kingshott/iodine";
7

Sekarang kita dapat mengatur pesan kesalahan khusus dengan menambahkan kunci ke properti


<form id="form" x-data="form" action="">
  <h1>Log In</h1>

  <label for="username">Username</label>
  <input name="username" id="username" type="text" data-rules='["required"]'>

  <label for="email">Email</label>
  <input name="email" type="email" id="email" data-rules='["required","email"]'>

  <label for="password">Password</label>
  <input name="password" type="password" id="password" data-rules='["required","minimum:8"]'>

  <label for="passwordConf">Confirm Password</label>
  <input name="passwordConf" type="password" id="passwordConf" data-rules='["required","minimum:8"]'>

  <input type="submit">
</form>
9 di Iodine

import kingshottIodine from "https://cdn.skypack.dev/@kingshott/iodine";
_8

Kami dapat menambahkan kedua panggilan ini di fungsi


Alpine.data("form", form);
Alpine.start();
function form(){ 
  return {
    username: {errorMessage:'', blurred:false},
    email: {errorMessage:'', blurred:false},
    password: {errorMessage:'', blurred:false},
    passwordConf: {errorMessage:'', blurred:false},
  }
}
0 kami untuk menyiapkan aturan ini

Dalam implementasi kami sebelumnya, kami dapat mengubah bidang "kata sandi" dan itu tidak akan membuat bidang "konfirmasi kata sandi" menjadi tidak valid. Tapi sekarang kami memetakan melalui semua masukan pada setiap perubahan, formulir kami akan selalu memastikan kata sandi dan konfirmasi kata sandi cocok

Beberapa sentuhan akhir

Satu refactor kecil yang bisa kita lakukan adalah membuat fungsi

<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js" defer></script>
8 hanya mengembalikan pesan jika inputnya kabur — ini bisa membuat HTML kita sedikit lebih pendek dengan hanya perlu memeriksa satu nilai sebelum memutuskan apakah akan membatalkan input. Artinya, atribut

Alpine.data("form", form);
Alpine.start();
function form(){ 
  return {
    username: {errorMessage:'', blurred:false},
    email: {errorMessage:'', blurred:false},
    password: {errorMessage:'', blurred:false},
    passwordConf: {errorMessage:'', blurred:false},
  }
}
_2 kita bisa sesingkat ini

import kingshottIodine from "https://cdn.skypack.dev/@kingshott/iodine";
_9

Inilah tampilan fungsi kita untuk memetakan melalui input dan menyetel data

let form = document.getElementById("form");

// This is a nice way of getting a list of checkable input elements
// And converting them into an array so we can use map/filter/reduce functions:
let inputs = [...form.querySelectorAll("input[data-rules]")];

function onSubmit(event) {
  inputs.map((input) => {
    if (Iodine.is(input.value, JSON.parse(input.dataset.rules)) !== true) {
      event.preventDefault();
      input.classList.add("invalid");
    }
  });
}
form.addEventListener("submit", onSubmit);
7 sekarang

<input name="email" type="email" id="email" data-rules='["required","email"]'>
0

Kami juga dapat menghapus peristiwa


Alpine.data("form", form);
Alpine.start();
function form(){ 
  return {
    username: {errorMessage:'', blurred:false},
    email: {errorMessage:'', blurred:false},
    password: {errorMessage:'', blurred:false},
    passwordConf: {errorMessage:'', blurred:false},
  }
}
_4 dan

Alpine.data("form", form);
Alpine.start();
function form(){ 
  return {
    username: {errorMessage:'', blurred:false},
    email: {errorMessage:'', blurred:false},
    password: {errorMessage:'', blurred:false},
    passwordConf: {errorMessage:'', blurred:false},
  }
}
5 dari semua input kami dengan mendengarkan peristiwa ini di elemen formulir induk. Namun, ada masalah dengan ini. acara
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js" defer></script>
_3 tidak menggelembung (elemen induk yang mendengarkan acara ini tidak akan meneruskannya saat diaktifkan pada anak-anak mereka). Untungnya, kita bisa mengganti blur dengan event

Alpine.data("form", form);
Alpine.start();
function form(){ 
  return {
    username: {errorMessage:'', blurred:false},
    email: {errorMessage:'', blurred:false},
    password: {errorMessage:'', blurred:false},
    passwordConf: {errorMessage:'', blurred:false},
  }
}
_7, yang pada dasarnya adalah event yang sama, tapi yang ini gelembung, jadi kita bisa mendengarkannya di elemen induk form kita

Akhirnya, kode kami mengembangkan banyak boilerplate. Jika kami mengubah nama input apa pun, kami harus menulis ulang data dalam fungsi kami setiap saat dan menambahkan pendengar acara baru. Untuk mencegah penulisan ulang data komponen setiap saat, kita dapat memetakan melalui input formulir yang memiliki atribut


Alpine.data("form", form);
Alpine.start();
function form(){ 
  return {
    username: {errorMessage:'', blurred:false},
    email: {errorMessage:'', blurred:false},
    password: {errorMessage:'', blurred:false},
    passwordConf: {errorMessage:'', blurred:false},
  }
}
8 untuk menghasilkan data komponen awal kita dalam fungsi

Alpine.data("form", form);
Alpine.start();
function form(){ 
  return {
    username: {errorMessage:'', blurred:false},
    email: {errorMessage:'', blurred:false},
    password: {errorMessage:'', blurred:false},
    passwordConf: {errorMessage:'', blurred:false},
  }
}
0. Ini membuat kode lebih dapat digunakan kembali untuk formulir tambahan. Yang perlu kita lakukan hanyalah menyertakan JavaScript dan menambahkan aturan sebagai atribut data dan kita siap melakukannya

Oh, dan hei, hanya karena sangat mudah dilakukan dengan Alpine, mari tambahkan transisi fade-in yang memberi perhatian pada pesan kesalahan

<input name="email" type="email" id="email" data-rules='["required","email"]'>
_1

Dan inilah hasil akhirnya. Validasi formulir yang reaktif dan dapat digunakan kembali dengan biaya pemuatan halaman minimal

CodePen Embed Fallback

Jika Anda ingin menggunakan ini di aplikasi Anda sendiri, Anda dapat menyalin fungsi

<input name="username" id="username" type="text" 
x-bind:class="{'invalid':username.errorMessage && username.blurred}" data-rules='["required"]'>
0 untuk menggunakan kembali semua logika yang telah kami tulis. Yang perlu Anda lakukan hanyalah mengonfigurasi atribut HTML Anda dan Anda siap untuk pergi