Formularvalidierung mit Ember.js
Formulare auf Webseiten sind so allgegenwärtig und selbstverständlich, dass man selten darüber nachdenkt. Trotzdem kann sich wahrscheinlich jeder Internetnutzer schnell an ein Formular erinnern, das nicht optimal funktioniert. Besonders beim Validieren von Formularen scheint es unendlich viele Varianten zu geben, wobei man auch im Jahr 2017 immer noch viele mangelhafte Formulare in freier Wildbahn antrifft.
Was macht ein gutes Formular aus?
Die meisten Aspekte, die es bei Formularen und deren Validierung zu berücksichtigen gilt, werden schon an einem einfachen Registrierungsformular deutlich:
- Weiss ich im Voraus, was für Eingaben in den verschiedenen Formularfeldern verlangt werden?
- Wann werde ich über eventuelle Fehler in meinen Eingaben informiert?
- Kann ich diese Fehler leicht beheben?
Eine gute Metrik für die Qualität eines Formulars ist die Zeit, die Nutzer durchschnittlich zum Ausfüllen benötigen. Eine Suche nach “best practices” für Formularvalidierung liefert diverse, gute Artikel, die verschiedene Varianten vergleichen.
Statt direkt zu den konkreten Empfehlungen für gute Formulare zu springen, lohnt es sich jedoch zunächst ein paar grundsätzliche Regeln für das Design von User Interfaces zu betrachten. Einige Einträge aus Aral Balkan’s “User Interface Design Principles” lassen sich direkt auf Formulare und ihre Validierung anwenden:
- Prevent, don’t scold: Ein gutes UI beugt Fehler vor, statt den User mit Fehlermeldungen zurechtzuweisen.
- Give sufficient feedback: Der Nutzer muss sich nie fragen, ob eine bestimmte Aktion gerade funktioniert hat oder nicht. Das UI steht über visuelles Feedback in ständigem Dialog mit dem Nutzer.
- Innocent until proven guilty: Eine Fehlermeldung zu einem Formularfeld sollte erst angezeigt werden, nachdem der Nutzer seine Eingabe im Feld abgeschlossen hat.
Aus den Grundlagen können wir zusammen mit den Ergebnissen der verschiedenen Studien ein paar Anforderungen für ein gutes Formular definieren:
- Das Formular ist hilfreich beschriftet. Neben einem aussagekräftigen Namen für das Formularfeld gehört dazu – falls nötig – auch ein beschreibender Text. Grundlage sollte hier sein, wie wahrscheinlich ein Fehler des Nutzers ist. Eine Beschreibung “Max. 50 Zeichen” im Nutzername-Feld ist nicht sinnvoll, ein Hinweis bei einer exotischen Passwort-Richtlinie (“Mindestens 8 Zeichen, keine Sonderzeichen ausser _ . :”) dagegen schon eher.
- Nach Abschluss der Eingabe erhält der Nutzer sofort Feedback: Fehlermeldungen werden beim Verlassen des Formularfelds (
onBlur
) angezeigt.
Formulare in Ember.js
Nun ist es an der Zeit, das Gelernte im Frontend-Framework der Wahl anzuwenden. In der Adfinis SyGroup ist dies aktuell Ember.js.
Wie man es aus der JavaScript-Welt so kennt, gibt es für jedes Problem viele verschiedene Lösungen. Ember Observer listet 32 Addons in der Formular-Kategorie, Google findet 222’000 Ergebnisse für ember form validation
. Einige Ergebnisse verdienen es jedoch hervorgehoben zu werden:
- ember-validations: Nr. 1 im Google-Suchergebnis, 873 Github-Stars. Der erste Satz im README lautet jedoch:
> This addon is no longer actively developed. At DockYard we have switched over to using ember-changeset-validations together with ember-changeset. - ember-changeset: Stellt ein sog.
Changeset
bereit, das Änderungen auf einem Ember-Model inkl. möglicher Validierungsfehler abbildet. Bildet zusammen mit ember-changeset-validations eine gute Grundlage für Validierungen aller Art. - ember-form-for: Erstes Suchergebnis im Ember Observer. Stellt eine sehr einfache und angenehme API zur Definition von Formularfeldern bereit:
{{#form-for newUser as |f|}}
{{f.text-field "firstName"}}
{{f.text-field "lastName"}}
{{f.select-field "gender" "unknown male female"}}
{{f.date-field "birthDate"}}
{{/form-for}}
Leider bietet ember-form-for jedoch keine “out-of-the-box”-Unterstützung für das Verstecken von Validierungsfehlern bis der Nutzer mit dem jeweiligen Feld interagiert hat (siehe Issue #122).
Aus dieser Situation heraus ist in unserem letzten Ember-Projekt das neue Addon ember-validated-formentstanden, das eine ähnliche API wie ember-form-for
bereitstellt und für die Validierungen auf ember-changeset
und ember-changeset-validations
zurückgreift. Mit dem Addon verfolgen wir folgende Ziele:
- Expliziter Fokus auf Formularvalidierung. Clientseitige Formularvalidierung soll nicht nur ein Nebenaspekt, sondern der Hauptfokus sein.
- Out-of-the-box UX. Fehlermeldungen werden erst
onBlur
oder nach Klick auf den submit-Button angezeigt. - Keep it simple. Statt eine Fülle von verschiedenen Formularkomponenten zu implementieren, sollen spezielle Formularelemente selbst integriert werden können.
Das Template eines typischen Formulars sieht mit ember-validated-form
z.B. so aus:
{{#validated-form
model = (changeset model UserValidations)
on-submit = (action "submit")
submit-label = 'Save' as |f|}}
{{f.input label="First name" name="firstName"}}
{{f.input label="Last name" name="lastName"}}
{{f.input type="textarea" label="About me" name="aboutMe"}}
{{f.input
type = "select"
label = "Country"
name = "country"
options = countries
value = model.country
}}
{{f.input type="radioGroup" label="Gender" name="gender" options=genders}}
{{/validated-form}}
Für die Validierungsregeln wird ember-changeset-validations
verwendet:
// validations/user.js
import {
validatePresence,
validateLength
} from 'ember-changeset-validations/validators';
export default {
firstName: [
validatePresence(true),
validateLength({min: 3, max: 40})
],
lastName: [
validatePresence(true),
validateLength({min: 3, max: 40})
],
aboutMe: [ validateLength({allowBlank: true, max: 200}) ],
country: [ validatePresence(true) ],
gender: [ validatePresence(true) ]
};
Zusammen mit Bootstrap sieht das Ergebnis dann in etwa so aus:
…und kann auch selbst probiert werden
Fazit
Formularvalidierung ist kein einfaches Thema, und es gibt wie so oft keine Patentlösung.
Trotzdem hoffen wir mit ember-validated-form
dazu beizutragen, dass in Zukunft immer weniger frustrierende Formulare im Web anzutreffen sind. Wir freuen uns über jede Art von Feedback auf Github!