แบบฟอร์มและการตรวจสอบความถูกต้องในปฏิกิริยาไอออนิก

เผยแพร่แล้ว: 2022-03-10
สรุปอย่างรวดเร็ว ↬ Ionic Framework ให้การสนับสนุนชั้นหนึ่งสำหรับการสร้างแอปพลิเคชันที่รวดเร็วและปรับให้เหมาะกับมือถือสำหรับแพลตฟอร์มใด ๆ โดยใช้ React ในบทช่วยสอนนี้ คุณจะได้เรียนรู้วิธีสร้างฟอร์มเมื่อทำงานกับ Ionic React และวิธีทำให้ฟอร์มเหล่านี้โต้ตอบได้ โดยการเพิ่มกฎการตรวจสอบด้วยคำแนะนำข้อความที่เป็นประโยชน์

Ionic Framework เป็นชุดเครื่องมือ UI สำหรับสร้างแอปพลิเคชันมือถือข้ามแพลตฟอร์มโดยใช้ HTML, CSS และ JavaScript การเปิดตัว Ionic 5 ในต้นปี 2020 มาพร้อมกับการสนับสนุนอย่างเป็นทางการสำหรับ React ทำให้นักพัฒนา React สามารถสร้างแอปพลิเคชั่นมือถือได้อย่างง่ายดายโดยใช้เครื่องมือที่พวกเขาชื่นชอบ อย่างไรก็ตาม ไม่มีการรองรับการทำงานกับฟอร์มมากนัก และไลบรารี่ที่มีอยู่จำนวนมากที่พร้อมใช้งานสำหรับการสร้างฟอร์มในระบบนิเวศ React นั้นไม่ได้เล่นได้ดีกับคอมโพเนนต์ของ Ionic Framework

คุณจะได้เรียนรู้วิธีสร้างแบบฟอร์มโดยใช้ส่วนประกอบอินพุต UI ของ Ionic React ในบทช่วยสอนนี้ คุณยังจะได้เรียนรู้วิธีการใช้ไลบรารีเพื่อช่วยในการตรวจสอบการเปลี่ยนแปลงอินพุตของฟอร์มและการตอบสนองต่อกฎการตรวจสอบความถูกต้อง สุดท้าย คุณจะได้เรียนรู้วิธีทำให้โปรแกรมอ่านหน้าจอเข้าถึงแบบฟอร์มได้โดยการเพิ่มข้อความที่เป็นประโยชน์ลงในแอตทริบิวต์ ARIA ของข้อมูลที่ป้อน

ส่วนประกอบแบบฟอร์มของอิออน

แบบฟอร์มเป็นส่วนสำคัญของแอปพลิเคชันบนเว็บและมือถือส่วนใหญ่ในปัจจุบัน ไม่ว่าคุณจะเปิดใช้งานการเข้าถึงส่วนที่ถูกจำกัดของแอปพลิเคชันของคุณผ่านการลงทะเบียนผู้ใช้และแบบฟอร์มการเข้าสู่ระบบ หรือรวบรวมคำติชมจากผู้ใช้ของคุณ คุณต้องสร้างแบบฟอร์มในบางจุดในวงจรชีวิตของแอปพลิเคชันของคุณ

Ionic มีส่วนประกอบที่สร้างไว้ล่วงหน้าสำหรับการทำงานกับแบบฟอร์ม ซึ่งบางส่วนรวมถึง IonItem , IonLabel , IonInput , IonCheckbox และ IonRadio เราสามารถรวมส่วนประกอบเหล่านี้เพื่อสร้างรูปแบบที่ดูเป็นมาตรฐานโดยไม่ต้องใส่สไตล์ลงไปเอง

ตัวอย่างเช่นรหัสต่อไปนี้:

 <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>

จะให้แบบฟอร์มการเข้าสู่ระบบแก่เราซึ่งมีลักษณะดังนี้:

แบบฟอร์มการเข้าสู่ระบบมาตรฐานบน iOS (ตัวอย่างขนาดใหญ่)

ส่วนประกอบแบบฟอร์มของ Ionic นั้นดูดีบน iOS หรือ Android ที่แกะกล่องออกมา แต่อาจใช้งานไม่ได้เล็กน้อยหากคุณทำงานกับ React เช่นเดียวกับเครื่องมือส่วนใหญ่ในระบบนิเวศของ React คุณต้องตัดสินใจว่าคุณต้องการสร้างแบบฟอร์มของคุณอย่างไรในด้านการทำงานและการเข้าถึง ทั้งสองสิ่งนี้มีความสำคัญพอๆ กันกับการออกแบบ

แม้ว่าจะมีตัวช่วยแบบฟอร์ม React ให้เลือกมากมาย แต่ส่วนใหญ่ใช้ไม่ได้กับองค์ประกอบของฟอร์มของ Ionic ฉันสงสัยว่าเหตุผลหลักสำหรับเรื่องนี้ก็คือเหตุการณ์เกิดขึ้นเมื่อค่าของฟิลด์เปลี่ยนแปลงใน Ionic คือ onIonChange ในขณะที่ไลบรารีฟอร์มที่มีอยู่ส่วนใหญ่จะฟัง onChange

เปลี่ยนเหตุการณ์ที่ทริกเกอร์เมื่อฟิลด์เปลี่ยนแปลง (ตัวอย่างขนาดใหญ่)

React Hook Form: ไลบรารีฟอร์มปฏิกิริยาขนาดเล็กและรวดเร็ว

โชคดีที่ไม่ใช่ความหายนะและความเศร้าโศก ฉันเพิ่งเจอ React Hook Form (RHF) ซึ่งเป็นห้องสมุดสำหรับการทำงานกับแบบฟอร์มในโครงการ React ให้การสนับสนุนสำหรับส่วนประกอบที่มีการควบคุมหรือไม่มีการควบคุมและการตรวจสอบความถูกต้องของอินพุต และ API เป็นแบบ hooks จึงทำงานได้เฉพาะกับส่วนประกอบที่ใช้งานได้เท่านั้น

คุณลักษณะที่น่าสนใจที่สุดสำหรับนักพัฒนา Ionic React — ในความคิดของฉัน — คือส่วนประกอบ <Controller /> ของ wrapper ที่มีให้สำหรับการทำงานกับส่วนประกอบที่ควบคุม ส่วนประกอบมี onChangeName prop ซึ่งสามารถใช้เพื่อระบุชื่อเหตุการณ์การเปลี่ยนแปลงสำหรับอินสแตนซ์ของส่วนประกอบใดก็ตามที่คุณส่งผ่าน ฉันจะแสดงให้คุณเห็นว่าสิ่งนี้ทำให้การทำงานกับฟอร์มใน Ionic เป็นเรื่องง่ายได้อย่างไรในหัวข้อต่อไปนี้

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

การสร้างแบบฟอร์มลงทะเบียน

มาดูกันว่า RHF ช่วยเราในด้านฟังก์ชันการทำงานของแบบฟอร์มได้อย่างไรในขณะที่เราสร้างแบบฟอร์มการลงทะเบียนใน Ionic หากคุณกำลังใช้งาน Ionic CLI เวอร์ชันล่าสุด (รัน npm i -g @ionic/cli เพื่อยืนยัน) ให้เริ่มแอป Ionic ใหม่ด้วย React โดยเรียกใช้คำสั่งต่อไปนี้:

 ionic start myApp blank --type=react

ฉันใช้เทมเพลตเปล่าที่นี่ คุณควรจะสามารถเขียนแบบฟอร์มที่มีอยู่ของคุณใหม่เพื่อใช้ไลบรารี React Hook Form ได้อย่างง่ายดาย โดยเฉพาะอย่างยิ่งถ้าคอมโพเนนต์ของคุณถูกเขียนเป็น Functional Components

หมายเหตุ: คุณควรลบองค์ประกอบ ExploreContainer และการนำเข้าใน Home.tsx ก่อนดำเนินการกับบทช่วยสอนนี้

ในการเริ่มต้นใช้งานแบบฟอร์มของคุณ ให้ติดตั้งแพ็คเกจ React Hook Form โดยเรียกใช้คำสั่งต่อไปนี้ในไดเรกทอรีรากของโครงการของคุณ:

 yarn add react-hook-form

สิ่งนี้จะทำให้ไลบรารี React Hook Form พร้อมใช้งานในโครงการของคุณ มาสร้างช่องใส่แบบฟอร์มโดยใช้ไลบรารีกันเถอะ เปิดไฟล์ Home.tsx และแทนที่เนื้อหาด้วยสิ่งต่อไปนี้:

 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;

ซึ่งจะทำให้คุณมีแบบฟอร์มที่มีฟิลด์เดียวเพื่อรวบรวมที่อยู่อีเมล มาแยกส่วนที่สำคัญกัน (เน้นที่บล็อคโค้ด)

ขั้นแรก เราทำลายโครงสร้างค่าส่งคืนของ useForm() hook จาก RHF handleSubmit ส่งค่าอินพุตของคุณไปยังฟังก์ชันตัวจัดการที่คุณระบุเมื่อแบบฟอร์มผ่านการตรวจสอบความถูกต้อง control เป็นวัตถุที่มีวิธีการที่ใช้สำหรับการลงทะเบียนส่วนประกอบควบคุมลงใน RHF

ต่อไป เรามีบล็อกไอเท็มแบบฟอร์มมาตรฐาน แต่ต่างจากตัวอย่างสำหรับแบบฟอร์มการเข้าสู่ระบบ เราส่งส่วนประกอบ IonInput ไปยังองค์ประกอบ <Controller /> ของ RHF ลงทะเบียนเหตุการณ์การเปลี่ยนแปลงโดยการตั้งค่าอุปกรณ์ onChangeName ของ <Controller /> เป็นเหตุการณ์การเปลี่ยนแปลงของ Ionic ชื่อและตั้งค่าการ control prop เป็นวัตถุควบคุมจากการเรียกใช้ useForm()

จนถึงตอนนี้ยังดีอยู่ แต่คุณอาจพบว่าตัวเองใช้รหัสเดียวกันซ้ำแล้วซ้ำเล่า คุณสามารถลองสร้างส่วนประกอบ Input ที่นำกลับมาใช้ใหม่ได้ซึ่งสร้างช่องป้อนข้อมูลด้วยคุณสมบัติที่กำหนด

สร้างไฟล์ในไดเร็กทอรี src/components ชื่อ Input.tsx และเพิ่มโค้ดต่อไปนี้ลงในไฟล์:

 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;

ส่วนประกอบนี้ได้รับพร็อพ name และตัวเลือก control component และส่วนประกอบ label และแสดงฟิลด์อินพุตโดยใช้ส่วนประกอบฟอร์มไอออนิกที่เปิดตัวก่อนหน้านี้ ซึ่งจะช่วยลดจำนวนโค้ดที่คุณต้องเขียนเมื่อสร้างช่องใส่แบบฟอร์ม คุณสามารถทำส่วนที่เหลือของแบบฟอร์มโดยใช้ส่วนประกอบนี้ แก้ไขไฟล์ Home.tsx โดยเปลี่ยนแปลงดังนี้:

 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;

ด้วยการตั้งค่าของคุณจนถึงตอนนี้ คุณจะมีอาร์เรย์ของฟิลด์อินพุตของฟอร์ม ( name เป็นคุณสมบัติที่จำเป็นเท่านั้น) โดยแต่ละฟิลด์จะแสดงผลโดยใช้องค์ประกอบ Input จากก่อนหน้านี้ คุณสามารถทำสิ่งนี้ให้ดียิ่งขึ้นไปอีกและมีข้อมูลภาคสนามของคุณในไฟล์ JSON ทำให้โค้ดภายในส่วนประกอบของคุณสะอาดหมดจด ณ จุดนี้ แอปของคุณ (ทำงานที่ https://localhost:8100 ด้วยคำสั่ง ionic serve ) ควรมีลักษณะดังนี้:

หน้าแบบฟอร์มลงทะเบียน (iOS) (ตัวอย่างขนาดใหญ่)

การตรวจสอบฟิลด์เป็นอย่างไร?

คุณอาจสังเกตเห็นว่าช่องป้อนข้อมูลของแบบฟอร์มของเรายังไม่มีตรรกะในการตรวจสอบความถูกต้อง หากเป็นแอปสำหรับใช้งานจริง อาจก่อให้เกิดผลกระทบที่ไม่พึงประสงค์มากมาย เว้นแต่ API ของคุณจะตั้งค่าให้ตรวจสอบข้อมูลขาเข้า อย่างไรก็ตาม API ของคุณต้องตรวจสอบข้อมูลขาเข้าเสมอ

RHF มาพร้อมกับการตรวจสอบความถูกต้องซึ่งสอดคล้องกับมาตรฐาน HTML สำหรับการตรวจสอบแบบฟอร์มในตัว วิธีนี้ใช้ได้ผลดีสำหรับการตรวจสอบความถูกต้องอย่างง่าย เช่น การสร้างฟิลด์ที่จำเป็น หรือการตั้งค่าความยาวฟิลด์ต่ำสุดและสูงสุด หากคุณต้องการใช้ตรรกะการตรวจสอบที่ซับซ้อน ฉันขอแนะนำให้ใช้ใช่ แม้ว่าคุณจะใช้ไลบรารีการตรวจสอบความถูกต้องของอ็อบเจ็กต์สคีมาก็ตาม RHF ก็รองรับ Yup ได้ทันที

เรียกใช้คำสั่งต่อไปนี้เพื่อติดตั้งไลบรารี (และพิมพ์):

 yarn add yup @types/yup

ต่อไป เพิ่มสิ่งนี้ในการนำเข้าส่วนประกอบของคุณ:

 import { object, string } from 'yup'; const Home: React.FC = () => { ... }

จากนั้น เพิ่มโค้ดต่อไปนี้ที่ด้านบนของคอมโพเนนต์ของคุณ:

 const Home: React.FC = () => { const validationSchema = object().shape({ email: string().required().email(), fullName: string().required().min(5).max(32), password: string().required().min(8), }); // ... }

ที่นี่ เราได้สร้างอ็อบเจ็กต์สคีมาและเพิ่มกฎการตรวจสอบให้กับแต่ละพร็อพเพอร์ตี้โดยใช้ yup ชื่อในออบเจ็กต์ต้องตรงกับชื่อในแท็กอินพุตของฟอร์มของคุณ มิฉะนั้น กฎของคุณจะไม่ถูกเรียกใช้

สุดท้าย อัปเดต useForm() hook ของคุณเพื่อใช้สคีมาที่เรากำหนดโดยการตั้งค่าคุณสมบัติ validationSchema ดังนี้:

 const { control, handleSubmit } = useForm({ validationSchema, });

ตอนนี้ เมื่อคุณคลิกที่ปุ่มส่ง ตัวจัดการ handleSubmit จะไม่ถูกเรียกใช้ และข้อมูลในฟอร์มจะไม่ถูกส่ง แม้ว่าเราจะต้องการสิ่งนี้ แต่ดูเหมือนว่าผู้ใช้จะไม่มีทางรู้ว่าเกิดอะไรขึ้น มาแก้ไขปัญหานี้โดยแสดงคำแนะนำข้อความเมื่อกรอกข้อมูลไม่ถูกต้อง

ขั้นแรก อัปเดตองค์ประกอบ Input ให้มีลักษณะดังนี้:

 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;

ที่นี่ เราได้อัปเดตองค์ประกอบของเราเพื่อรับคุณสมบัติเสริมเพิ่มเติมซึ่งเป็นวัตถุข้อผิดพลาดจาก RHF และเราจะแสดงข้อความแสดงข้อผิดพลาดในช่องป้อนข้อมูลที่ส่งคืนทุกครั้งที่มีข้อผิดพลาด สิ่งสุดท้าย เพิ่มอ็อบเจกต์ error ให้กับออบเจกต์ที่ถูกทำลายและอัปเดตส่วนประกอบในลูปของคุณ:

 const { control, handleSubmit, errors } = useForm({ validationSchema, });
 {formFields.map((field, index) => ( <Input {...field} control={control} key={index} errors={errors} /> ))}
แบบฟอร์มการลงทะเบียนพร้อมข้อความแสดงข้อผิดพลาด (iOS) (ตัวอย่างขนาดใหญ่)

แบบฟอร์มของคุณจะแสดงภาพเมื่อผู้ใช้ทำสิ่งที่ไม่ถูกต้อง ใช่ช่วยให้คุณเปลี่ยนข้อความแสดงข้อผิดพลาดได้ คุณสามารถทำได้โดยส่งสตริงไปยังวิธีการตรวจสอบที่คุณกำลังใช้ สำหรับอีเมล คุณสามารถทำสิ่งต่อไปนี้ได้ ตัวอย่างเช่น

 { email: string() .email('Please provide a valid email address') .required('This is a required field'), }

การปรับปรุงการช่วยสำหรับการเข้าถึง

ส่วนประกอบของไอออนิกมักจะถูกห่อหุ้มไว้เหนือองค์ประกอบดั้งเดิมที่สอดคล้องกัน ซึ่งหมายความว่าพวกเขายอมรับแอตทริบิวต์ที่มีอยู่ขององค์ประกอบส่วนใหญ่ (ถ้าไม่ใช่ทั้งหมด) ส่วนใหญ่ คุณสามารถปรับปรุงช่องป้อนข้อมูลและทำให้ผู้ใช้ที่มีความบกพร่องทางสายตาเข้าถึงได้ง่ายขึ้นโดยการตั้งค่าแอตทริบิวต์ ARIA ด้วยข้อความที่เกี่ยวข้อง

หากต้องการดำเนินการต่อด้วยตัวอย่างแบบฟอร์มการลงทะเบียนของเรา ให้เปิดไฟล์ Input.tsx และทำการเปลี่ยนแปลงต่อไปนี้:

 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;

คอมโพเนนต์ IonInput เริ่มต้นที่เราส่งไปยัง Controller ในขณะนี้มีแอตทริบิวต์ที่ไม่ถูกต้องของ aria-invalid เพื่อระบุว่าฟิลด์มีข้อผิดพลาดหรือไม่ และแอตทริบิวต์ aria-describedby เพื่อชี้ไปที่ข้อความแสดงข้อผิดพลาดที่เกี่ยวข้อง ขณะนี้ข้อความแสดงข้อผิดพลาดถูกปิดด้วย span ที่มีการตั้งค่าบทบาท ARIA เป็น "ข้อผิดพลาด" ตอนนี้ เมื่อฟิลด์ของคุณมีข้อผิดพลาด โปรแกรมอ่านหน้าจอจะเน้นฟิลด์นั้นและอ่านข้อความแสดงข้อผิดพลาด

  • คุณจะพบ GitHub repo ที่นี่

บทสรุป

ยินดีด้วย! คุณได้เรียนรู้วิธีสร้างและตรวจสอบแบบฟอร์มเมื่อสร้างแอปข้ามแพลตฟอร์มโดยใช้ Ionic คุณยังได้เห็นว่ามันง่ายเพียงใดในการทำให้ผู้ใช้ที่มีความบกพร่องทางสายตาเข้าถึงช่องป้อนข้อมูลของคุณได้ หวังว่าบทช่วยสอนนี้จะมอบแพลตฟอร์มที่แข็งแกร่งที่คุณสามารถใช้ได้เมื่อสร้างฟอร์มในแอป Ionic React มีองค์ประกอบอื่นๆ สำหรับการสร้างแบบฟอร์ม (เช่น การเลือกและวิทยุ) ที่เราไม่ได้สำรวจในบทช่วยสอนนี้ แต่คุณสามารถค้นหาและอ่านเพิ่มเติมเกี่ยวกับพวกเขาได้ในเอกสารอย่างเป็นทางการ

อ้างอิง

  • Ionic Framework Docs
  • ตอบสนองตะขอแบบฟอร์ม
  • ได้เอกสาร
  • Phil Haack เกี่ยวกับการตรวจสอบที่อยู่อีเมล
  • การเข้าถึงบน MDN Web Docs