Bentuk Dan Validasi Dalam Ionic React
Diterbitkan: 2022-03-10Ionic Framework adalah UI Toolkit untuk membangun aplikasi seluler lintas platform menggunakan HTML, CSS, dan JavaScript. Rilis Ionic 5 pada awal 2020 datang dengan dukungan resmi untuk React, memungkinkan pengembang React untuk dengan mudah membangun aplikasi seluler menggunakan alat favorit mereka. Namun, tidak banyak dukungan untuk bekerja dengan formulir, dan banyak perpustakaan yang ada yang tersedia untuk membangun formulir di ekosistem React tidak cocok dengan komponen Kerangka Kerja Ionic.
Anda akan belajar cara membuat formulir menggunakan komponen input UI Ionic React dalam tutorial ini. Anda juga akan mempelajari cara menggunakan pustaka untuk membantu mendeteksi perubahan input formulir dan merespons aturan validasi. Terakhir, Anda akan belajar membuat formulir Anda dapat diakses oleh pembaca layar dengan menambahkan teks bermanfaat ke atribut ARIA input Anda.
Komponen Bentuk Ionic
Formulir adalah bagian penting dari sebagian besar aplikasi web dan seluler saat ini. Baik Anda mengaktifkan akses ke bagian aplikasi yang dibatasi melalui pendaftaran pengguna dan formulir masuk atau mengumpulkan umpan balik dari pengguna, Anda harus — pada titik tertentu dalam siklus hidup aplikasi Anda — membuat formulir.
Ionic menyediakan komponen bawaan untuk bekerja dengan formulir — beberapa di antaranya termasuk IonItem
, IonLabel
, IonInput
, IonCheckbox
dan IonRadio
. Kami dapat menggabungkan komponen-komponen ini untuk membuat bentuk yang terlihat standar tanpa menambahkan gaya apa pun sendiri.
Misalnya, kode berikut:
<form className="ion-padding"> <IonItem> <IonLabel position="floating">Username</IonLabel> <IonInput /> </IonItem> <IonItem> <IonLabel position="floating">Password</IonLabel> <IonInput type="password" /> </IonItem> <IonItem lines="none"> <IonLabel>Remember me</IonLabel> <IonCheckbox defaultChecked={true} slot="start" /> </IonItem> <IonButton className="ion-margin-top" type="submit" expand="block"> Login </IonButton> </form>
Akan memberi kita formulir login yang terlihat seperti ini:
Di luar kotak, komponen formulir Ionic tampak hebat di iOS atau Android, tetapi mereka bisa sedikit berat jika Anda bekerja dengan React. Seperti kebanyakan alat di ekosistem React, Anda harus memutuskan bagaimana Anda ingin membangun formulir Anda dalam hal fungsionalitas dan aksesibilitas — keduanya sama pentingnya dengan desain.
Meskipun sudah ada begitu banyak helper formulir React yang tersedia untuk dipilih, kebanyakan dari mereka tidak bekerja dengan komponen formulir Ionic. Saya menduga alasan utama untuk ini adalah bahwa acara dipicu ketika nilai bidang berubah di Ionic adalah onIonChange
, sedangkan sebagian besar perpustakaan formulir yang ada mendengarkan onChange
.
Formulir Kait Bereaksi: Pustaka Formulir Bereaksi Kecil Dan Cepat
Untungnya, itu tidak semua malapetaka dan kesuraman. Saya baru-baru ini menemukan React Hook Form (RHF), perpustakaan untuk bekerja dengan formulir di proyek React. Ini memberikan dukungan untuk komponen terkontrol atau tidak terkontrol dan validasi input, dan API berbasis kait sehingga hanya berfungsi dengan komponen fungsional.
Fitur yang paling menarik bagi pengembang Ionic React — menurut saya — adalah komponen pembungkus <Controller />
yang disediakannya untuk bekerja dengan komponen yang dikontrol. Komponen memiliki prop onChangeName
yang dapat digunakan untuk menentukan nama peristiwa perubahan untuk instance komponen apa pun yang Anda berikan padanya. Saya akan menunjukkan kepada Anda bagaimana ini membuat bekerja dengan formulir di Ionic sangat mudah di bagian berikut.
Membangun Formulir Pendaftaran
Mari kita lihat bagaimana RHF membantu kita dengan fungsionalitas formulir saat kita membuat formulir pendaftaran di Ionic. Jika Anda menjalankan versi terbaru Ionic CLI (jalankan npm i -g @ionic/cli
untuk mengonfirmasi), mulai aplikasi Ionic baru dengan React dengan menjalankan perintah berikut:
ionic start myApp blank --type=react
Saya menggunakan template kosong di sini. Anda seharusnya dapat menulis ulang formulir yang ada untuk menggunakan pustaka Formulir Kait React dengan mudah, terutama jika komponen Anda ditulis sebagai Komponen Fungsional.
Catatan: Anda harus menghapus komponen ExploreContainer
dan impornya di Home.tsx sebelum melanjutkan dengan tutorial ini.
Untuk memulai dengan formulir Anda, instal paket React Hook Form dengan menjalankan perintah berikut di direktori root proyek Anda:
yarn add react-hook-form
Ini akan membuat library React Hook Form tersedia di proyek Anda. Mari buat bidang input formulir menggunakan perpustakaan. Buka file Home.tsx dan ganti isinya dengan berikut ini:
import { IonContent, IonPage, IonText, IonItem, IonLabel, IonInput, IonButton } from "@ionic/react"; import React from "react"; import "./Home.css"; import { Controller, useForm } from 'react-hook-form'; const Home: React.FC = () => { const { control, handleSubmit } = useForm(); const registerUser = (data) => { console.log('creating a new user account with: ', data); } return ( <IonPage> <IonContent className="ion-padding"> <IonText color="muted"> <h2>Create Account</h2> </IonText> <form onSubmit={handleSubmit(registerUser)}> <IonItem> <IonLabel position="floating">Email</IonLabel> <Controller as={<IonInput type="email" />} name="email" control={control} onChangeName="onIonChange" /> </IonItem> <IonButton expand="block" type="submit" className="ion-margin-top"> Register </IonButton> </form> </IonContent> </IonPage> ); }; export default Home;
Ini memberi Anda formulir dengan satu bidang untuk mengumpulkan alamat email. Mari kita urai bagian-bagian penting (disorot di blok kode).
Pertama, kami merusak nilai kembalian hook useForm()
dari RHF. handleSubmit
meneruskan nilai input Anda ke fungsi handler yang Anda tentukan saat formulir melewati validasi. control
adalah objek yang berisi metode yang digunakan untuk mendaftarkan komponen yang dikontrol ke dalam RHF.
Selanjutnya, kita memiliki blok item form standar, tetapi tidak seperti contoh untuk form login, kita meneruskan komponen IonInput
ke komponen <Controller />
RHF, mendaftarkan event perubahan dengan mengatur prop onChangeName
<Controller />
ke event perubahan Ionic name, dan atur prop control
ke objek kontrol dari memanggil useForm()
.
Ini bagus sejauh ini, tetapi Anda mungkin mendapati diri Anda mengulangi kode yang hampir sama berulang-ulang. Anda dapat mencoba membuat komponen Input
yang dapat digunakan kembali yang membangun bidang input dengan properti yang diberikan.
Buat file di direktori src/components bernama Input.tsx dan tambahkan kode berikut ke file:
import React, { FC } from "react"; import { IonItem, IonLabel, IonInput } from "@ionic/react"; import { Controller, Control } from "react-hook-form"; export interface InputProps { name: string; control?: Control; label?: string; component?: JSX.Element; } const Input: FC<InputProps> = ({ name, control, component, label, }) => { return ( <> <IonItem> {label && ( <IonLabel position="floating">{label}</IonLabel> )} <Controller as={component ?? <IonInput />} name={name} control={control} onChangeName="onIonChange" /> </IonItem> </> ); }; export default Input;
Komponen ini menerima prop name
dan control
opsional, component
dan label
props dan merender bidang input menggunakan komponen bentuk ionik yang diperkenalkan sebelumnya. Ini mengurangi jumlah kode yang harus Anda tulis saat membuat bidang input formulir. Anda dapat menyelesaikan sisa formulir Anda menggunakan komponen ini. Edit file Home.tsx dengan perubahan berikut:
import { IonContent, IonPage, IonText, IonInput, IonButton, IonCheckbox, IonItem, IonLabel } from "@ionic/react"; import React from "react"; import "./Home.css"; import { useForm } from "react-hook-form"; import Input, { InputProps } from "../components/Input"; const Home: React.FC = () => { const { control, handleSubmit } = useForm(); const formFields: InputProps[] = [ { name: "email", component: <IonInput type="email" />, label: "Email", }, { name: "fullName", label: "Full Name", }, { name: "password", component: <IonInput type="password" clearOnEdit={false} />, label: "Password", }, ]; const registerUser = (data) => { console.log("creating a new user account with: ", data); }; return ( <IonPage> <IonContent> <div className="ion-padding"> <IonText color="muted"> <h2>Create Account</h2> </IonText> <form onSubmit={handleSubmit(registerUser)}> {formFields.map((field, index) => ( <Input {...field} control={control} key={index} /> ))} <IonItem> <IonLabel>I agree to the terms of service</IonLabel> <IonCheckbox slot="start" /> </IonItem> <IonButton expand="block" type="submit" className="ion-margin-top"> Register </IonButton> </form> </div> </IonContent> </IonPage> ); }; export default Home;
Dengan pengaturan Anda sejauh ini, Anda memiliki larik bidang input formulir Anda ( name
adalah satu-satunya properti yang diperlukan), dengan setiap bidang dirender menggunakan komponen Input
dari sebelumnya. Anda dapat mengambil ini lebih jauh dan memiliki data bidang Anda dalam file JSON, menjaga kode di dalam komponen Anda dengan formulir tetap bersih. Pada titik ini, aplikasi Anda (berjalan di https://localhost:8100 dengan perintah ionic serve
) akan terlihat seperti ini:
Bagaimana dengan Validasi Lapangan?
Anda mungkin telah memperhatikan bahwa bidang input formulir kami belum memiliki logika validasi. Jika ini adalah aplikasi yang ditujukan untuk penggunaan di dunia nyata, itu dapat menyebabkan banyak efek yang tidak diinginkan kecuali API Anda disiapkan untuk memvalidasi data yang masuk. Omong-omong, API Anda harus selalu memvalidasi data yang masuk.
RHF hadir dengan validasi yang sejalan dengan standar HTML untuk validasi formulir bawaan. Ini berfungsi baik untuk validasi sederhana seperti membuat bidang wajib diisi atau mengatur panjang bidang minimum dan maksimum. Jika Anda ingin menggunakan logika validasi yang kompleks, saya akan merekomendasikan menggunakan Yup. Meskipun Anda dapat menggunakan pustaka validasi skema objek apa pun, RHF mendukung Yup di luar kotak.
Jalankan perintah berikut untuk menginstal perpustakaan (dan pengetikan):
yarn add yup @types/yup
Selanjutnya, tambahkan ini ke impor komponen Anda:
import { object, string } from 'yup'; const Home: React.FC = () => { ... }
Kemudian, tambahkan kode berikut di bagian atas komponen Anda:
const Home: React.FC = () => { const validationSchema = object().shape({ email: string().required().email(), fullName: string().required().min(5).max(32), password: string().required().min(8), }); // ... }
Di sini, kami telah membuat skema objek dan menambahkan aturan validasi ke setiap properti menggunakan yup
. Nama di objek harus cocok dengan nama di tag input formulir Anda jika tidak, aturan Anda tidak akan dipicu.
Terakhir, perbarui kait useForm()
Anda untuk menggunakan skema yang telah kita definisikan dengan menyetel properti validationSchema
seperti ini:
const { control, handleSubmit } = useForm({ validationSchema, });
Sekarang, ketika Anda mengklik tombol kirim, handler handleSubmit
tidak dipanggil dan data formulir tidak dikirimkan. Meskipun ini persis seperti yang kami inginkan, sepertinya tidak ada cara bagi pengguna untuk mengetahui apa yang terjadi. Mari kita perbaiki ini dengan menunjukkan petunjuk teks ketika sebuah bidang tidak diisi dengan benar.
Pertama, perbarui komponen Input
agar terlihat seperti berikut:
import React, { FC } from "react"; import { IonItem, IonLabel, IonInput, IonText } from "@ionic/react"; import { Controller, Control, NestDataObject, FieldError } from "react-hook-form"; export interface InputProps { name: string; control?: Control; label?: string; component?: JSX.Element; errors?: NestDataObject<Record<string, any>, FieldError>; } const Input: FC<InputProps> = ({ name, control, component, label, errors, }) => { return ( <> <IonItem> {label && <IonLabel position="floating">{label}</IonLabel>} <Controller as={component ?? <IonInput />} name={name} control={control} onChangeName="onIonChange" /> </IonItem> {errors && errors[name] && ( <IonText color="danger" className="ion-padding-start"> <small>{errors[name].message}</small> </IonText> )} </> ); }; export default Input;
Di sini, kami telah memperbarui komponen kami untuk menerima properti opsional tambahan yang merupakan objek kesalahan dari RHF, dan kami menampilkan pesan kesalahan di bidang input yang dikembalikan setiap kali ada kesalahan. Satu hal terakhir, tambahkan objek kesalahan ke objek Anda yang rusak dan perbarui komponen di loop Anda:
const { control, handleSubmit, errors } = useForm({ validationSchema, });
{formFields.map((field, index) => ( <Input {...field} control={control} key={index} errors={errors} /> ))}
Formulir Anda sekarang memberikan isyarat visual saat pengguna tidak melakukan sesuatu dengan benar. Yup memungkinkan Anda untuk mengubah pesan kesalahan. Anda dapat melakukan ini dengan meneruskan string ke metode validasi yang Anda gunakan. Untuk email, sebagai contoh, Anda dapat melakukan hal berikut:
{ email: string() .email('Please provide a valid email address') .required('This is a required field'), }
Meningkatkan Aksesibilitas
Komponen ionik biasanya membungkus elemen asli yang sesuai, artinya mereka menerima sebagian besar — jika tidak semua — atribut elemen yang ada. Anda dapat meningkatkan bidang masukan dan membuatnya lebih mudah diakses oleh pengguna tunanetra dengan menyetel atribut ARIA dengan teks yang relevan.
Untuk melanjutkan dengan contoh formulir pendaftaran kami, buka file Input.tsx dan buat perubahan berikut:
import React, { FC } from "react"; import { IonItem, IonLabel, IonInput, IonText } from "@ionic/react"; import { Controller, Control, NestDataObject, FieldError } from "react-hook-form"; export interface InputProps { name: string; control?: Control; label?: string; component?: JSX.Element; errors?: NestDataObject<Record<string, any>, FieldError>; } const Input: FC<InputProps> = ({ name, control, component, label, errors, }) => { return ( <> <IonItem> {label && <IonLabel position="floating">{label}</IonLabel>} <Controller as={ component ?? ( <IonInput aria-invalid={errors && errors[name] ? "true" : "false"} aria-describedby={`${name}Error`} /> ) } name={name} control={control} onChangeName="onIonChange" /> </IonItem> {errors && errors[name] && ( <IonText color="danger" className="ion-padding-start"> <small> <span role="alert" id={`${name}Error`}> {errors[name].message} </span> </small> </IonText> )} </> ); }; export default Input;
Komponen IonInput
default yang kita teruskan ke Controller
sekarang menyertakan atribut aria-invalid
untuk menunjukkan apakah bidang memiliki kesalahan, dan atribut aria-describedby
untuk menunjuk ke pesan kesalahan yang sesuai. Pesan kesalahan sekarang dibungkus dengan span
yang memiliki peran ARIA yang disetel ke "kesalahan". Sekarang, ketika bidang Anda memiliki kesalahan, pembaca layar akan menyorot bidang itu dan membacakan pesan kesalahan.
- Anda akan menemukan repo GitHub di sini.
Kesimpulan
Selamat! Anda telah mempelajari cara membuat dan memvalidasi formulir saat membuat aplikasi lintas platform menggunakan Ionic. Anda juga telah melihat betapa mudahnya membuat bidang masukan Anda dapat diakses oleh pengguna tunanetra. Semoga tutorial ini menyediakan platform yang solid yang dapat Anda gunakan saat membuat formulir di aplikasi Ionic React Anda. Ada komponen lain untuk membangun formulir (seperti pilih dan radio) yang tidak kami jelajahi dalam tutorial ini, tetapi Anda dapat menemukan dan membaca lebih lanjut tentangnya di dokumen resmi.
Referensi
- Dokumen Kerangka Ionic
- Bentuk Kait Bereaksi
- Ya Dok
- Phil Haack tentang Memvalidasi Alamat Email
- Aksesibilitas di Dokumen Web MDN