Formen und Validierung in Ionic React
Veröffentlicht: 2022-03-10Ionic Framework ist ein UI-Toolkit zum Erstellen plattformübergreifender mobiler Anwendungen mit HTML, CSS und JavaScript. Die Veröffentlichung von Ionic 5 Anfang 2020 kam mit offizieller Unterstützung für React, sodass React-Entwickler problemlos mobile Anwendungen mit ihren bevorzugten Tools erstellen können. Es gibt jedoch nicht viel Unterstützung für die Arbeit mit Formularen, und viele der vorhandenen Bibliotheken, die zum Erstellen von Formularen im React-Ökosystem verfügbar sind, spielen nicht gut mit den Komponenten von Ionic Framework.
In diesem Tutorial erfahren Sie, wie Sie Formulare mit den UI-Eingabekomponenten von Ionic React erstellen. Sie lernen auch, wie Sie eine Bibliothek verwenden, um Änderungen an Formulareingaben zu erkennen und auf Validierungsregeln zu reagieren. Schließlich lernen Sie, Ihre Formulare für Bildschirmlesegeräte zugänglich zu machen, indem Sie den ARIA-Attributen Ihrer Eingaben hilfreichen Text hinzufügen.
Ionics Formularkomponenten
Formulare sind heute ein wichtiger Bestandteil der meisten Web- und Mobilanwendungen. Unabhängig davon, ob Sie den Zugriff auf eingeschränkte Teile Ihrer Anwendung über Benutzerregistrierungs- und Anmeldeformulare ermöglichen oder Feedback von Ihren Benutzern sammeln, müssen Sie – irgendwann im Lebenszyklus Ihrer Anwendung – ein Formular erstellen.
Ionic bietet vorgefertigte Komponenten für die Arbeit mit Formularen – einige davon beinhalten IonItem
, IonLabel
, IonInput
, IonCheckbox
und IonRadio
. Wir können diese Komponenten kombinieren, um standardmäßig aussehende Formulare zu erstellen, ohne selbst Stile hinzuzufügen.
Zum Beispiel der folgende Code:
<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>
Geben Sie uns ein Anmeldeformular, das so aussieht:
Standardmäßig sehen die Formularkomponenten von Ionic auf iOS oder Android großartig aus, aber sie können etwas unhandlich sein, wenn Sie mit React arbeiten. Wie bei den meisten Tools im React-Ökosystem müssen Sie entscheiden, wie Sie Ihre Formulare erstellen möchten, wenn es um Funktionalität und Zugänglichkeit geht – beides ist ebenso wichtig wie das Design.
Obwohl bereits so viele React-Formularhelfer zur Auswahl stehen, funktionieren die meisten nicht mit den Formularkomponenten von Ionic. Ich vermute, der Hauptgrund dafür ist, dass das Ereignis, das ausgelöst wird, wenn sich ein Feldwert in Ionic ändert, onIonChange
ist, während die meisten vorhandenen Formularbibliotheken auf onChange
.
Reaktionshakenformular: Kleine und schnelle Reaktionsformularbibliothek
Zum Glück ist es nicht alles Untergangsstimmung. Ich bin kürzlich auf React Hook Form (RHF) gestoßen, eine Bibliothek zum Arbeiten mit Formularen in React-Projekten. Es bietet Unterstützung für kontrollierte oder unkontrollierte Komponenten und Eingabevalidierung, und die API ist Hooks-basiert, sodass sie nur mit funktionalen Komponenten funktioniert.
Das ansprechendste Feature für Ionic React-Entwickler ist meiner Meinung nach die Wrapper-Komponente <Controller />
, die sie für die Arbeit mit kontrollierten Komponenten bereitstellt. Die Komponente hat eine onChangeName
, die verwendet werden kann, um den Änderungsereignisnamen für jede Komponenteninstanz anzugeben, die Sie ihr übergeben. Wie das Arbeiten mit Formularen in Ionic dadurch wirklich einfach wird, zeige ich Ihnen in den folgenden Abschnitten.
Erstellen eines Anmeldeformulars
Mal sehen, wie RHF uns bei der Formularfunktionalität hilft, wenn wir ein Registrierungsformular in Ionic erstellen. Wenn Sie die neueste Version der Ionic-CLI ausführen (führen Sie zur Bestätigung npm i -g @ionic/cli
aus), starten Sie eine neue Ionic-App mit React, indem Sie den folgenden Befehl ausführen:
ionic start myApp blank --type=react
Ich habe hier eine leere Vorlage verwendet. Sie sollten in der Lage sein, Ihre vorhandenen Formulare problemlos umzuschreiben, um die React Hook Form-Bibliothek zu verwenden, insbesondere wenn Ihre Komponenten als funktionale Komponenten geschrieben sind.
Hinweis: Sie sollten die ExploreContainer
Komponente und ihren Import in Home.tsx entfernen, bevor Sie mit diesem Tutorial fortfahren.
Um mit Ihrem Formular zu beginnen, installieren Sie das React Hook Form-Paket, indem Sie den folgenden Befehl im Stammverzeichnis Ihres Projekts ausführen:
yarn add react-hook-form
Dadurch wird die React Hook Form-Bibliothek in Ihrem Projekt verfügbar. Lassen Sie uns mithilfe der Bibliothek ein Formulareingabefeld erstellen. Öffnen Sie die Datei Home.tsx und ersetzen Sie ihren Inhalt durch Folgendes:
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;
Dadurch erhalten Sie ein Formular mit einem einzigen Feld zum Erfassen einer E-Mail-Adresse. Lassen Sie uns die wichtigen Teile aufschlüsseln (im Codeblock hervorgehoben).
Zuerst destrukturieren wir den Rückgabewert des useForm()
von RHF. handleSubmit
übergibt die Werte Ihrer Eingabe an die von Ihnen angegebene Handler-Funktion, wenn das Formular die Validierung besteht. control
ist ein Objekt, das Methoden enthält, die zum Registrieren gesteuerter Komponenten in RHF verwendet werden.
Als nächstes haben wir einen Standard-Formularelementblock, aber im Gegensatz zum Beispiel für das Anmeldeformular übergeben wir die IonInput
-Komponente an die <Controller />
-Komponente von RHF, registrieren das Änderungsereignis, indem wir die onChangeName
-Prop von <Controller />
auf das Änderungsereignis von Ionic setzen name, und setzen Sie die control
Prop auf das Control-Objekt, indem useForm()
aufrufen.
Das ist soweit gut, aber Sie werden vielleicht feststellen, dass Sie fast denselben Code immer und immer wieder wiederholen. Sie könnten versuchen, eine wiederverwendbare Eingabekomponente zu Input
, die ein Eingabefeld mit bestimmten Eigenschaften erstellt.
Erstellen Sie im Verzeichnis src/components eine Datei mit dem Namen Input.tsx und fügen Sie der Datei den folgenden Code hinzu:
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;
Diese Komponente erhält eine name
-Prop und optionale control
, component
und label
-Props und rendert ein Eingabefeld unter Verwendung der zuvor eingeführten ionischen Formularkomponenten. Dies reduziert die Menge an Code, die Sie beim Erstellen von Formulareingabefeldern schreiben müssen. Mit dieser Komponente können Sie den Rest Ihres Formulars fertigstellen. Bearbeiten Sie die Datei Home.tsx mit den folgenden Änderungen:
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;
Mit Ihrem bisherigen Setup haben Sie ein Array der Eingabefelder Ihres Formulars ( name
ist die einzige erforderliche Eigenschaft), wobei jedes Feld mit der Input
-Komponente von früher gerendert wird. Sie können sogar noch weiter gehen und Ihre Felddaten in einer JSON-Datei haben, wodurch der Code in Ihren Komponenten mit Formularen sauber bleibt. Zu diesem Zeitpunkt sollte Ihre App (die unter https://localhost:8100 mit dem Befehl ionic serve
läuft) so aussehen:
Wie sieht es mit der Feldvalidierung aus?
Sie haben vielleicht bemerkt, dass die Eingabefelder unseres Formulars noch keine Validierungslogik haben. Wenn dies eine App wäre, die für den Einsatz in der realen Welt gedacht wäre, könnte dies zu vielen unerwünschten Effekten führen, es sei denn, Ihre API ist so eingerichtet, dass eingehende Daten validiert werden. Übrigens muss Ihre API eingehende Daten immer validieren.
RHF wird mit einer Validierung geliefert, die dem HTML-Standard für die integrierte Formularvalidierung entspricht. Dies eignet sich hervorragend für einfache Validierungen, z. B. um ein Feld als Pflichtfeld festzulegen oder minimale und maximale Feldlängen festzulegen. Wenn Sie eine komplexe Validierungslogik verwenden möchten, würde ich die Verwendung von Yup empfehlen. Während Sie jede Objektschema-Validierungsbibliothek verwenden können, unterstützt RHF Yup standardmäßig.
Führen Sie den folgenden Befehl aus, um die Bibliothek (und Eingaben) zu installieren:
yarn add yup @types/yup
Fügen Sie als Nächstes Folgendes zu den Importen Ihrer Komponente hinzu:
import { object, string } from 'yup'; const Home: React.FC = () => { ... }
Fügen Sie dann den folgenden Code oben in Ihrer Komponente hinzu:
const Home: React.FC = () => { const validationSchema = object().shape({ email: string().required().email(), fullName: string().required().min(5).max(32), password: string().required().min(8), }); // ... }
Hier haben wir ein Objektschema erstellt und jeder Eigenschaft mithilfe von yup
Validierungsregeln hinzugefügt. Die Namen im Objekt müssen mit den Namen in den Eingabe-Tags Ihres Formulars übereinstimmen, andernfalls werden Ihre Regeln nicht ausgelöst.
Aktualisieren Sie abschließend Ihren useForm()
Hook so, dass er das von uns definierte Schema verwendet, indem Sie die validationSchema
-Eigenschaft wie folgt festlegen:
const { control, handleSubmit } = useForm({ validationSchema, });
Wenn Sie jetzt auf die Senden-Schaltfläche klicken, wird der handleSubmit
Handler nicht aufgerufen und die Formulardaten werden nicht gesendet. Dies ist zwar genau das, was wir wollten, aber es sieht so aus, als ob der Benutzer nicht wissen kann, was passiert. Lassen Sie uns dies beheben, indem wir Texthinweise anzeigen, wenn ein Feld nicht korrekt ausgefüllt ist.
Aktualisieren Sie zunächst die Input
Komponente so, dass sie wie folgt aussieht:
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;
Hier haben wir unsere Komponente aktualisiert, um eine zusätzliche optionale Eigenschaft zu erhalten, die das Fehlerobjekt von RHF ist, und wir zeigen eine Fehlermeldung im zurückgegebenen Eingabefeld an, wenn ein Fehler auftritt. Eine letzte Sache, fügen Sie das Fehlerobjekt zu Ihrem destrukturierten Objekt hinzu und aktualisieren Sie die Komponente in Ihrer Schleife:
const { control, handleSubmit, errors } = useForm({ validationSchema, });
{formFields.map((field, index) => ( <Input {...field} control={control} key={index} errors={errors} /> ))}
Ihre Formulare bieten jetzt visuelle Hinweise, wenn ein Benutzer etwas nicht richtig macht. Mit Yup können Sie die Fehlermeldung ändern. Sie können dies tun, indem Sie eine Zeichenfolge an die von Ihnen verwendete Validierungsmethode übergeben. Für E-Mails können Sie beispielsweise Folgendes tun:
{ email: string() .email('Please provide a valid email address') .required('This is a required field'), }
Verbesserung der Zugänglichkeit
Die Komponenten von Ionic sind normalerweise Wrapper für das entsprechende native Element, was bedeutet, dass sie die meisten – wenn nicht alle – der vorhandenen Attribute dieses Elements akzeptieren. Sie können Ihre Eingabefelder verbessern und für sehbehinderte Benutzer zugänglicher machen, indem Sie ARIA-Attribute mit relevantem Text setzen.
Um mit unserem Beispielregistrierungsformular fortzufahren, öffnen Sie die Datei Input.tsx und nehmen Sie die folgenden Änderungen vor:
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;
Die standardmäßige IonInput
Komponente, die wir an Controller
übergeben, enthält jetzt ein aria-invalid
Attribut, das angibt, ob das Feld einen Fehler enthält, und ein aria-describedby
Attribut, das auf die entsprechende Fehlermeldung verweist. Die Fehlermeldung wird nun mit einer span
umschlossen, deren ARIA-Rolle auf „Fehler“ gesetzt ist. Wenn Ihr Feld nun einen Fehler aufweist, hebt ein Screenreader dieses Feld hervor und liest die Fehlermeldung vor.
- Das GitHub-Repo finden Sie hier.
Fazit
Glückwünsche! Sie haben gelernt, wie Sie Formulare erstellen und validieren, wenn Sie plattformübergreifende Apps mit Ionic erstellen. Sie haben auch gesehen, wie einfach es ist, Ihre Eingabefelder für Benutzer mit Sehbehinderung zugänglich zu machen. Hoffentlich bietet dieses Tutorial eine solide Plattform, die Sie beim Erstellen von Formularen in Ihren Ionic React-Apps verwenden können. Es gibt andere Komponenten zum Erstellen von Formularen (z. B. select und radios), die wir in diesem Tutorial nicht untersucht haben, aber Sie können mehr darüber in den offiziellen Dokumenten finden und lesen.
Verweise
- Ionic Framework-Dokumentation
- Hakenform reagieren
- Ja, Dokumente
- Phil Haack über die Validierung von E-Mail-Adressen
- Zugänglichkeit auf MDN Web Docs