Formular-Eingabevalidierung im Online-Übungssystem

Autor: Immo Schulz-Gerlach, ZDI
Version: 2.1 – 12. August 2024
[PDF-Version] [ePub-Version]

Überblick

Im Jahr 2011 wurde erstmals eine clientseitige Eingabevalidierung im Online-Übungssystem ermöglicht. Dafür zuständig war eine JavaScript-Library, die eben vor einem Submitversuch die entsprechend gekennzeichneten Eingabefelder auf Gültigkeit der Eingaben überprüfte, also z.B. leere Pflichtfelder meldete oder Texteingaben in Zahlenfeldern.

Weil die Ansteuerung dieser JavaScript-Validierung (allein durch Einträge im class-Attribut von HTML-Tags) eine Übungssystem-spezifische Eigenentwicklung war, wurde die Version 1 dieses Handbuchs dazu geschrieben.

Inzwischen wird kein JavaScript mehr für Formularvalidierung mehr benötigt, der HTML-5-Standard sieht eigene HTML-Attribute für die Deklaration von zu validierenden Constraints vor. Dass kein JavaScript mehr benötigt wird, ist nur einer der Vorteile der HTML-5-Syntax. Darüber hinaus bieten die neuen Feldtypen weitere Vorteile wie Eingabeunterstützungen. So kann ein Zahlenfeld z.B. in Desktop-Browsern (für Maussteuerung) vom Browser direkt mit „Spin-Buttons“, also kleinen Pfeil-Icons zum De- und Inkrementieren des Zahlenwerts versehen werden, und für Smartphone-Browser kann gezielt eine Zehnertastatur mit oder ohne Komma-Taste statt einer für Textfelder sonst üblichen Buchstabentastatur auf dem Touchscreen eingeblendet werden.

Außerdem ist es von Vorteil, dass (weitestgehend) keine Übungssystem-spezifische Syntax mehr benötigt wird, sondern eben direkt auf den systemübergreifend anwendbaren HTML-Standard gesetzt werden kann.

Daher wird heute eher der Einsatz der HTML-5-Validierung empfohlen, die auch mehr Möglichkeiten bietet als die ältere JavaScript-Validierung.

Das erste Kapitel dieses Handbuchs geht daher zunächst auf den Einsatz von HTML-5-Validierung ein. Da es sich um einen gut dokumentierten Standard handelt, wird dieses Übungssystem-Handbuch nicht alle Möglichkeiten ausführlich beschreiben, sondern eher ein paar simple Beispiele für die wichtigsten Szenarien, insbesondere für die zuvor schon mit der JavaScript-Variante möglichen Validierungen zusammenstellen und auf die Übungssystem-eigenen Mechanismen zur Aktivierung bestimmen Funktionen/Hervorhebungen eingehen.

Die Dokumentation zur bisherigen JavaScript-Validierung (die nach wie vor funktioniert), finden Sie anschließend im Kapitel 2.

Kurzreferenz Formularklassen

Vorab eine Übersicht der möglichen Klassen, die im class-Attribut eines <form>-Tags eingetragen werden können. Die folgenden Kapitel gehen näher darauf ein.

Klasse Funktion
validation-styles Aktiviert Übungssystem-eigene CSS-Stile und JavaScripte für den Einsatz mit HTML-5-basierter Eingabevalidierung (siehe Kapitel 1).
required-checkbox-groups Aktiviert JavaScript zur Unterstützung von Checkbox-Gruppen als Pflichtfeld, siehe Checkboxen als Pflichtfelder. In der Regel mit validation-styles in Kombination zu verwenden.
validated Aktiviert die bisherige JavaScript-Validierung, siehe Kapitel 2. Sollte nicht mit den beiden obigen Klassen kombiniert werden!

Das Online-Übungssystem wird Ihre Aufgabenseiten automatisch nach diesen Klassen durchsuchen und immer, wenn es so markiertes Formular findet, die benötigten JavaScript-Dateien automatisch einbinden (Script-Tags ins ausgelieferte HTML injizieren)1.

Kombination beider Validierungen

Prinzipiell können Sie HTML-5-Tags mit der JavaScript-basierten Validierung kombinieren, wenn Ihnen die eingeschränkteren Möglichkeiten der letzten ausreichen und Sie deren Einblendung von Texten bevorzugen.

So blendet die JavaScript-Validierung ihre Fehlermeldung eigenständig, browserunabhängig und dauerhaft sichtbar hinter dem Eingabefeld ein:

Meldung der Javascript-Validierung
Meldung der Javascript-Validierung

Bei der HTML-5-Variante dagegen sorgen die Browser selbst für eine Anzeige von Fehlerhinweisen, was je nach Browser durchaus unterschiedlich aussehen kann, z.B.:

Firefox Safari Chrome
Number-Element in Firefox Number-Element in Safari Number-Element in Chrome

Wenn Sie beides kombinieren möchten, tragen Sie im form-Tag nur die Klasse validated ein und verzichten Sie auf die anderen Klasse aus obiger Übersichtstabelle! Für die Inputs können Sie dann z.B. HTML-5-Input-Typen verwenden und ihnen im class-Attribut dann zusätzlich noch die von der JavaScript-Lösung benötigten Klassen zuordnen (siehe 2. Kapitel).


1. Formular-Eingabevalidierung per HTML 5

HTML-5-Validierung können Sie prinzipiell jederzeit benutzen, dazu wird keine spezielle Funktionalität des Online-Übungssystems benötigt.

Sie müssen dazu lediglich Standard-HTML-Attribute zu Ihrem Formular (form-Tag) oder den Formularelementen (wie input-Tags) hinzufügen.

Hier ein paar Einstiegslinks zur Dokumentation in MDN:

Um allerdings Übungssystem-eigene CSS-Stile oder die Übungssystem-eigene Lösung für „Pflicht-Checkbox-Gruppen“ zu aktivieren, sind dem Formular-Tag (<form>) Übungssystem-spezifische Klassen im class-Attribut zuzuweisen (siehe Tabelle Kurzreferenz Formularklassen). Bei Vorhandensein mindestens einer dieser Klassen lädt das Online-Übungssystem ein eigenes kleines JavaScript mit Zusatzfunktionen hinzu.

Formatierung der Eingabefelder durchs Online-Übungssystem

Das Standard-CSS des Online-Übungssystems wird bereits versuchen, Input-Felder, deren Eingaben nicht die Constraints erfüllen (wie leere Pflichtfelder, Zahlenfelder mit Text darin oder Zahlenfelder mit einer Zahl außerhalb des erlaubten Werftenbereiches etc.), hervorzuheben, derzeit durch roten Rahmen.

Dieses Standard-CSS allein hat aber ein paar Nachteile:

Wenn Sie dagegen dem <form>-Tag des HTML-Formulars im class-Attribut die Klasse validation-styles hinzufügen, aktiviert das Online-Übungssystem zusätzlich per JavaScript insbesondere derzeit folgende Funktionen (Änderungen vorbehalten):

Beispiel für ein Formular mit validation-styles-Klasse, einem Pflichtfeld und einem Zahlenfeld (für beliebige Fließkommazahlen ≥ 0):

<form class="validation-styles" action="$WebAssignServer/$Veranstaltername/Einsendung/$KursNr/$VersionsNr/$AufgabenheftNr/$AufgabenNr" method="post">
    …
    <input type="text" name="FeldA1" required>
    …
    <input type="number" inputmode="decimal" min="0" step="any" name="FeldA2">
    …
</form>

Beispiele für Umsetzung von Validierungen mit HTML 5

Bei den folgenden Beispielen wird davon ausgegangen (also nicht mehr extra mit angegeben), dass diese in einem Formularelement mit Klasse validation-styles stehen:

<form class="validation-styles" action="$WebAssignServer/$Veranstaltername/Einsendung/$KursNr/$VersionsNr/$AufgabenheftNr/$AufgabenNr" method="post">
    …
    …Beispiel-Elemente…
    …
</form>

Die HTML-Validierung wird zwar auch ohne diese Class funktionieren, aber die empfohlene CSS-Darstellung wird dadurch aktiviert, siehe Formatierung der Eingabefelder durchs Online-Übungssystem

Pflichtfelder

Um ein Feld als Pflichtfeld zu kennzeichnen, versehen Sie es einfach mit dem Attribut required (als eigenständiges Attribut – nicht, wie es bei der alten JS-Lösung der Fall war, als Klasse), z.B.:

<input type="text" name="FeldA1" required>

Das geht prinzipiell mit beliebigen Input-Feldern, also insbesondere

Zahlenfelder

Um ein Feld als Feld für eine Zahleneingabe zu markieren, können Sie den Input-Type von text auf number ändern. Das hat verschiedene Auswirkungen, z.B.:

Im Übrigen gibt es noch diverse weitere HTML-Attribute für Text- oder numerische Inputs, z.B. pattern, mit dem ein Textmuster als regulärer Ausdruck festgelegt werden kann.

Inputmode

Zusätzlich zu den oben genannten Attributen wie type="number", um ein Eingabefeld überhaupt auf Zahleneingaben festzulegen, sowie Constraint-Attributen wie min, max, step, die den Wertebereich der möglichen Zahlen einschränken, kann es sinnvoll sein, zusätzlich das Attribut inputmode anzugeben, um einen Texteingabemodus dazu festzulegen. Das hat in Browsern auf typischen PCs mit Bildschirm, Tastatur und Maus keine Auswirkungen, kann aber auf gewissen Touchscreen-Geräten wie insbesondere Smartphones, die eine virtuelle Tastatur einblenden, ein abweichendes Tastaturlayout einstellen. Ohne Angabe wird ein Smartphone unter Umständen eine Standard-Texttastatur auch für Zahlenfelder einblenden, auf der die Eingabe von Zahlen vergleichsweise weniger komfortabel ist als z.B. auf einer reinen Zifferntastatur.

Für Zahleneingaben gibt es im Wesentlichen zwei Eingabemodi:

inputmode Tastatur
numeric Zifferntastatur. Je nach Gerät/Browser kann sie auch weitere Tasten enthalten, aber typisch sind ausschließlich Tasten für die Ziffern 0 bis 9. Damit lassen sich also im Zweifel keine Fließkommazahlen und auch keine Vorzeichen eingeben, also nur Ziffernfolgen / natürliche Zahlen.
decimal Zifferntastatur, die ein zur im Betriebssystem eingestellten Region passendes Dezimaltrennzeichen eingeben kann, in Deutschland also ein Komma, in Amerika einen Punkt. Auch hier ist nicht sichergestellt, dass ein Vorzeichen eingegeben werden kann! Android-Tastaturen im Decimal-Modus umfassen m.W. eine Minus-Taste, bei iOS dagegen gibt es wirklich nur die Ziffern und das Komma, siehe folgende Abbildung.

Fazit:

Das inputmode-Attirbut kann übrigens nicht nur mit type="number" kombiniert werden, sondern auch mit type="text". Das kann z.B. sinnvoll sein, falls Sie Spinner-Buttons verhindern wollen oder möchten, dass das eingegebene nationale Dezimaltrennersymbol unverändert gesendet und nicht – wie es bei type=number der Fall wäre – vom Browser vor der Einsendung durch einen Punkt ersetzt wird.

Typische Beispiele für Zahlenfelder

  1. Natürliche Zahlen / Ziffernfolgen (entspricht class="digits" bei der alten JavaScript-Validierung):
    <input type="number" inputmode="numeric" min="0" … >
    
    • Da kein step-Attribut angegeben wurde, gilt die Standard-Schrittweite von 1, was die Eingabemöglichkeit auf ganze Zahlen beschränkt.
    • inputmode="numeric" aktiviert die Zifferntastatur z.B. auf Smartphones (s.o.), die auf manchen Geräten keine Minustaste besitzt.
    • Das min-Attribut legt fest, dass negative Zahlen grundsätzlich nicht eingesendet werden dürfen (auch nicht, wenn die Minustaste vorhanden ist).
  2. beliebige ganze Zahlen (entspricht class="integer" bei der alten JavaScript-Validierung):
    <input type="number" … >
    
    • Da kein step-Attribut angegeben wurde, gilt die Standard-Schrittweite von 1, was die Eingabemöglichkeit auf ganze Zahlen beschränkt.
    • Ohne min-Attribut können auch negative ganze Zahlen eingegeben werden.
    • Es wurde keine Zifferntastatur angefordert, damit die Eingabe des Minus-Vorzeichens auch auf allen Touchscreen-Geräten überhaupt möglich ist.
  3. beliebige reelle Zahlen (entspricht class="number" bei der alten JavaScript-Validierung):
    <input type="number" step="any" … >
    
    • step="any" erlaubt beliebig viele Nachkommastellen.
    • Auch hier wird keine Zifferntastatur angefordert, da selbst die Dezimal-Tastatur (siehe nächstes Beispiel) nicht auf allen Endgeräten eine Minus-Vorzeicheneingabe ermöglicht!
  4. nicht-negative reelle Zahlen:
    <input type="number" inputmode="decimal" min="0" step="any" … >
    
    • Gegenüber dem obigen Beispiel wurde hier wieder der Wertebereich auf nicht-negative Zahlen begrenzt, indem min="0" festgelegt wurde,
    • und nun kann dem Smartphone-Nutzer auch wieder gefahrlos entgegengekommen werden, indem die Standard-Bildschirmtastatur durch eine Zehnertastatur mit zusätzlicher Kommataste ersetzt wird.
  5. Textfeld für natürliche Zahlen/Ziffernfolgen (verhindert die Einblendung von Spinner-Buttons):
    <input type="text" inputmode="numeric" pattern="\d*">
    
    • Hier wird dem Browser gesagt, dass er ein Textfeld anzeigen soll, in dem aber nur Text als gültig gilt, der ausschließlich aus Ziffern besteht. Letzteres wird über das Pattern-Attribut als regulärer Ausdruck festgelegt, wobei \d für eine Ziffer (digit) und * für „beliebig viele davon“ steht.
  6. Textfeld für ganze Zahlen mit oder ohne Vorzeichen (wobei hier auch + als Vorzeichen explizit erlaubt wird):
    <input type="text" pattern="[+-]?\d+">
    
    • Hier wird dem Browser gesagt, dass er ein Textfeld anzeigen soll, in dem aber nur Text als gültig gilt, der ausschließlich aus Ziffern und optional einem + oder - davor besteht. Ein Vorzeichen ohne Ziffern dahinter ist nicht gültig. (Das \d+ steht für mindestens eine Ziffer; [+-] steht für "Plus oder Minus" und das Fragezeichen dahinter macht das Ganze optional, so dass das Vorzeichen auch weggelassen werden darf.)

Die beiden letzten Beispiele wurden der Vollständigkeit halber mit aufgeführt. Sie verhindern durch Verwenden eines Text- statt Zahlenfelders insbesondere das Einblenden von „Spinner-Buttons“ (also Pfeil-Buttons zum Erhöhen oder Verringern des angezeigten aktuellen Werts, siehe folgende Abbildung) in Desktop-Browsern.

Gerade bei Eingabefeldern für sehr große Zahlen (z.B. in den Tausendern) wird kaum jemand diese Spinner-Buttons sinnvoll für die Eingabe nutzen, da es „ewig“ dauert, allein durch Drücken des Pfeil-nach-oben-Buttons den Wert schrittweise von 0 auf z.B. 12993 zu erhöhen – da hat man den Wert schneller eingetippt. Dennoch sind die Spinner-Buttons ja „eigentlich“ unschädlich – bis auf die Tatsache, dass sie das Risiko erhöhen, einen bereits eingegebenen Wert später beim Scrollen durch die Seite versehentlich zu verändern, indem man eben unbeabsichtigt einen dieser Spinner-Buttons anklickt. Genau wenn Sie solche versehentlichen „Spins“ verhindern möchten, können Sie also auf Muster wie in 5. und 6. zurückgreifen.

Dieser Textfeld-Workaround hat aber auch wieder seine Nachteile: Bei den Zahlenfeldern wie in den Beispielen 1 bis 4 kann der Browser bei Fehleingaben nämlich sinnvolle sprechende Meldungen ausgeben wie in folgender Abbildung:

Number-Element mit Spinner-Buttons und sinnvoller Fehlermeldung bei Validierung
Number-Element mit Spinner-Buttons und sinnvoller Fehlermeldung bei Validierung

Wenn Sie dagegen ein Textfeld mit Pattern verwenden, zeigt der Browser bei Fehleingaben lediglich eine Meldung der Art »Halten Sie sich ans vorgegebene Muster!«. Was aber genau das vorgegebene Muster ist, sollte dann aus Ihrem Aufgabentext hervorgehen, andernfalls ist das nicht sehr hilfreich.

Daher würden wir im Normalfall die ersten Varianten mit Zahlenfeldern eher empfehlen.

Bei Beispiel 6. kommt als weiterer Nachteil hinzu, dass der Smartphone-Browser hier typischerweise eine Buchstabentastatur anzeigen wird, die erst manuell auf Zahleneingabe umgeschaltet werden muss.

Checkboxen als Pflichtfelder

In diesem Punkt besteht ein wesentlicher Unterschied zwischen der HTML-5-Validierung und der bisherigen JavaScript-Validierung aus Kapitel 2:

Diese Problematik betrifft übrigens ausschließlich Checkboxen, nicht für Radiobuttons: Stellen wir obiges Beispiel auf Radiobuttons um:

<form class="validation-styles">
    <input type="radio" name="FeldA2" value="A" required>
    <input type="radio" name="FeldA2" value="B" required>
</form>

Der obige Beispielcode stellt bereits ganz ohne JavaScript-Nutzung schon im HTML-Standard sicher, dass einer der Radiobuttons dieser Gruppe markiert sein muss. (Die Markierung mehrerer davon wäre ja auch nicht möglich).

Auch hier würde es auch genügen, nur an einem dieser Inputs (z.B. dem ersten) das required-Attribut zu notieren, empfohlen wird aber, es in allen Inputs zu tun. Sofern Sie die Klasse validation-styles verwenden, macht das keinen Unterschied, da das Übungssystem im Zweifel fehlende required-Attribute an den restlichen Checkboxen nachträgt.


2. Formular-Eingabevalidierung per Java-Script (deprecated)

Das Online-Übungssystem bot seit 2011 die Möglichkeit, Formulare mit einer automatischen Prüfung der Eingaben per JavaScript auszustatten. Dies ist die ältere Technik, die weniger flexibel konfigurierbar ist, keinen Support für bestimmte virtuelle Smartphone-Tastaturen oder besondere Eingabeelemente wie Spin-Buttons an Zahlenfeldern bietet, und die auch nur funktioniert, sofern der Benutzer in seinem Browser JavaScript nicht abgeschaltet hat.

Dieses Verfahren wird für neu zu entwickelnde Aufgabenformulare nicht mehr empfohlen, steht aber nach wie vor zur Verfügung – wenn auch in erster Linie aus Gründen der Abwärtskompatibilität (damit bestehende Aufgaben, die es nutzen, weiterhin funktionieren und nicht angepasst werden müssen). Wir behalten uns dennoch vor, das Verfahren zukünftig einzustellen, falls es irgendwann nicht mehr ohne Codeanpassungen mit neueren Browsern kompatibel sein sollte.

Um diese JavaScript-Formularvalidierung zu nutzen, müssen Sie selbst keinen JavaScript-Code schreiben und auch keine Scriptdateien einbinden, sondern lediglich Ihren HTML-Code mit bestimmten class-Attributen versehen.

Dazu kann für einzelne Formularfelder festgelegt werden, ob sie z.B. Pflichtfelder sein sollen (d.h. nicht leer gelassen werden dürfen), ob sie nur Ziffern oder Zahlen (mit Fließkommadarstellung) oder ein Datum aufnehmen dürfen. So lange diese Bedingungen nicht sämtlich erfüllt sind, lässt sich das Formular nicht absenden.

Beispiel für Texteingabe in ein Zahlen-Feld
Beispiel für Texteingabe in ein Zahlen-Feld

Obige Abbildung zeigt beispielhaft eine Fehlermeldung für ein als numerisch markiertes Feld. Derartige Prüfungen vor dem Einsenden können (insbesondere bei automatisch nach Einsendeschluss bewerteten Aufgaben) Studierenden helfen, fehlerhafte Eingaben schon vor dem Einsenden (und nicht erst nach Erhalt der Korrektur) zu erkennen.

Einrichtung

Um für ein HTML-Formular die Eingabevalidierung zu aktivieren, fügen Sie dem Form-Tag die Klasse validated hinzu (<form … class="validated" …>…</form>). Weiterhin sind zu jedem Formularelement, für das eine Validierung stattfinden soll, die jeweiligen Validierungsregeln ebenfalls als Klasse (d.h. im class-Attribut) anzugeben. Insb. folgende Klassen sind möglich:

Klasse zulässige Eingaben
required Pflichtfeld: Das Feld darf nicht leer gelassen werden.
Die Klasse requiredlässt sich mit den folgenden Klassen kombinieren:
digits Eine Ziffernfolge (ohne weitere Zeichen wie Plus, Minus, Komma oder Punkt)
integer Eine Ziffernfolge optional mit Vorzeichen + oder - davor, aber ohne Dezimalstellen.
number Eine Zahl, die wahlweise mit Minus beginnen darf und entweder einen Punkt oder ein Komma als Dezimaltrenner (jedoch keinen Tausendertrenner) aufweisen darf.
Beispiele für korrekte Zahlen: „5“, „5,9“ oder „-456.99“. Ab sofort wird auch die wissenschaftliche Exponentenschreibweise unterstützt, z.B. „1,3e9“ für \(1,3·10^9\) oder „0.2E-14“ für \(0,2·10^{-14}\). Das E darf groß oder klein geschrieben werden, und einem positiven Exponenten darf, muss aber kein Vorzeichen (+) vorangestellt werden.
dateDE Datum im Format tt.mm.jjjj (also zweistelliger Tag, zweistelliger Monat, vierstelliges Jahr)
dateISO Datum im Format jjjj/(m)m/(t)t (vierstelliges Jahr, ein- oder zweistelliger Monat, ein- oder zweistelliger Tag, alternativ zu ‚/‘ ist auch ‚-‘ als Trennzeichen erlaubt)
url Absolute URL (muss mit http://, https:// oder ftp:// beginnen, andere URLs werden nicht erkannt)
email E-Mail-Adresse

Beispiel für ein validiertes Formular mit einem Pflichtfeld zur Eingabe einer Zahl:

<form class="validated" action="$WebAssignServer/$Veranstaltername/Einsendung/$KursNr/$VersionsNr/$AufgabenheftNr/$AufgabenNr" method="post">
    …
    <input type="text" class="number required" name="FeldA1">
    …
</form>

Hinweise


  1. Beachten Sie, dass dabei dann auch die jQuery-Library eingebunden wird, die wiederum ihr globales jQuery-Objekt auch unter der Alias-Variable $ ablegt. Falls Sie selbst ein anderes JavaScript-Framework wie Prototype o.ä. verwenden, das ebenfalls die Variable $ definiert, könnte es (je nach Reihenfolge der Einbindung beider Libraries) also dazu kommen, dass entweder Ihr Scriptcode oder die Formularvalidierung nicht korrekt funktioniert.  ↩

  2. Für diese Lösung wurde bewusst der Einsatz einer Klasse class="required" an Stelle des HTML-Attributs required gewählt: Falls im Client-Browser JavaScript inaktiv sein sollte, wird so zwar das Pflichtfeld-Constraint nicht sichergestellt, aber wenigstens ist jede gültige Eingabe (Kombination von Checkboxen) möglich. Hätte man statt dessen im HTML einfach ein required-Attribut mit ganz anderer Semantik eingesetzt und verließe sich darauf, dass dessen Semantik nachträglich per JavaScript modifiziert wird, so wäre die Aufgabe mit abgeschaltetem JavaScript nicht mehr korrekt bearbeitbar.  ↩