Zum Inhalt
wannacode

Formulare

Kurz gesagt: Ein Formular sendet nur die Felder mit einem name, die Beschriftung <label> verbindet Text und Feld, und die Attribute required, type, min, max und pattern lassen den Browser die Eingabe vor dem Senden prüfen.

Problem

Eine Bestellung ohne Daten

Der Shop bekommt Bestellungen ohne Namen und ohne Telefon. Die Käufer schwören, dass sie alles ausgefüllt haben. Hier ist das Formular an der Kasse. Füll es aus und klick auf „Jetzt bestellen“.

HTML, CSS, JS
index.html

Die Sandbox sendet nichts über das Netz. Stattdessen sagt die Konsole, was gesendet worden wäre: „Das Formular wurde gesendet: (keine Felder)“. Alles, was du getippt hast, ist auf der Seite geblieben. Es gibt noch ein zweites Zeichen: Ein Klick auf das Wort „Name“ setzt den Cursor nicht ins Feld. Auf dem Bildschirm stehen Text und Feld nebeneinander, aber nichts im Baum verbindet sie.

Die Idee

Das Formular, der name und die Beschriftung

Ein Formular (<form>) sammelt Felder und sendet sie zusammen. action sagt, wohin (/order), und method sagt, wie (post).

<form action="/order" method="post">
<label for="phone">Telefon</label>
<input id="phone" name="phone" type="tel">
<button type="submit">Jetzt bestellen</button>
</form>
  • name ist das, was gesendet wird. Beim Absenden macht der Browser für jedes Feld mit einem Namen ein Paar name=value: phone=0888123456. Ein Feld ohne name wird nicht gesendet, so voll es auch ist. Darum war die Bestellung leer.
  • <label> ist die Beschriftung des Felds. Sie wird mit for verbunden, das auf die id des Felds zeigt. Das Feld kann auch in der Beschriftung stehen: <label>Telefon <input name="phone"></label>. Dann braucht man for nicht.

Die Beschriftung gibt dem Feld im Barrierefreiheitsbaum einen Namen. Ein Screenreader sagt „Telefon, Texteingabe“, nicht nur „Texteingabe“. Ein Klick auf die Beschriftung fokussiert das Feld, und eine Checkbox mit Beschriftung lässt sich über ihren Text ankreuzen. Die Prüfungen in den Aufgaben finden das Feld über seine Beschriftung, so wie ein Mensch es tut.

id und name sind oft gleich, haben aber verschiedene Aufgaben. Die id ist für die Beschriftung und für CSS, und der name ist der Schlüssel in der Anfrage.

Die Idee

Die Arten von Feldern

<input> ist ein Feld, und type sagt, was es ist:

  • text (der Standard), email, tel: Text. Auf dem Handy öffnen email und tel eine Tastatur mit @ oder mit Ziffern.
  • number: eine Zahl, mit Pfeilen. min="1", max="10" und step="1" geben die Grenzen und die Schrittweite an.
  • checkbox: ein Ja-oder-Nein-Häkchen. Sie wird nur gesendet, wenn sie angekreuzt ist: gift=yes aus value="yes". Ohne value sendet sie gift=on.
  • radio: eine Wahl aus mehreren. Radiobuttons bilden eine Gruppe über einen gemeinsamen name: name="delivery" bei beiden, und value sagt, welcher gewählt ist. Gesendet wird nur der gewählte.

Weitere Felder:

  • <select> mit <option>: ein Dropdown. Es sendet den value der gewählten Option oder ihren Text, wenn es keinen value gibt.
  • <textarea>: Text über mehrere Zeilen, zum Beispiel ein Hinweis für den Kurier.
  • <fieldset> mit <legend>: eine Gruppe von Feldern mit einem Titel. Die Radiobuttons für die Lieferung stehen in einem fieldset, und die legend „Lieferung“ ist der Name der Gruppe. Ohne sie sagt ein Screenreader „An eine Filiale“, aber nicht, wofür die Filiale da ist.

Der Button. <button type="submit"> sendet das Formular. <button type="button"> tut von selbst nichts, seine Aktion steht in JavaScript. In einem Formular ist ein <button> ohne type ein submit. Schreib also immer den type.

Sieh es dir an

Die ganze Bestellung

Das Formular an der Kasse mit allen Arten von Feldern. Füll es aus, ändere die Stadt und die Lieferung und klick auf „Jetzt bestellen“. Kreuze „Als Geschenk verpacken“ an und klick noch einmal.

HTML, CSS, JS
index.html

Schau dir die Zeile in der Konsole an. Die Paare stehen in der Reihenfolge der Felder im Code. Die Stadt ist plovdiv: Der value wird gesendet, nicht der Text „Plovdiv“. Von der Lieferung ist nur der gewählte Button dabei. Die Checkbox fehlt, solange sie nicht angekreuzt ist. Der leere Hinweis wird als note= gesendet: Ein leeres Feld mit einem Namen ist trotzdem ein Feld.

Probier es aus

Repariere die Bestellung

Repariere das Formular von vorhin, damit die Bestellung vollständig ankommt. Die Texte „Name“, „Telefon“ und „Adresse“ werden zu den Beschriftungen ihrer Felder, und die Felder bekommen die Namen name, phone und address.

HTML, CSS, JS
index.html

Probier es aus

Finde den Fehler

Die Käuferin tippt einen Rabattcode und klickt auf „Code einlösen“. Die Bestellung wird gesendet, bevor sie ihre E-Mail-Adresse getippt hat. Welche Zeile ist schuld?

Wähle die Zeile mit dem Fehler.

Probier es aus

Ergänze

Welches Attribut der Beschriftung zeigt auf die id des Felds?

<label ="email">E-Mail</label>
<input id="email" name="email" type="email">

Die Idee

Die Prüfungen des Browsers

Eine Bestellung mit der E-Mail-Adresse anna oder mit der Menge 0 sollte nicht gesendet werden. Der Browser kann vieles von selbst prüfen, ohne eine Zeile JavaScript. Die Regeln sind Attribute des Felds:

  • required: Das Feld darf nicht leer sein. Bei einer Checkbox: Sie muss angekreuzt sein. Bei einer Radiogruppe: Es muss etwas gewählt sein.
  • type="email": Der Text muss wie eine E-Mail-Adresse aussehen (name@domain). Ein leeres Feld besteht, wenn es kein required gibt.
  • min und max: die Grenzen einer Zahl. step ist die Schrittweite: Bei step="1" besteht 2,5 nicht.
  • minlength und maxlength: wie viele Zeichen mindestens und höchstens.
  • pattern: ein Muster für den ganzen Text, wie ein regulärer Ausdruck. pattern="0[0-9]{9}" ist eine 0 und neun weitere Ziffern.

Wenn auf „Jetzt bestellen“ geklickt wird, prüft der Browser jedes Feld. Besteht eines nicht, wird das Formular nicht gesendet, und das Ereignis submit tritt gar nicht ein. Der Browser fokussiert das erste ungültige Feld und zeigt daneben eine Meldung in der Sprache des Browsers. Die Käuferin korrigiert es, klickt noch einmal, und der Browser prüft von vorn.

novalidate am <form> schaltet diese Prüfungen ab. Man braucht es, wenn die Seite selbst prüft und die Fehler mit eigenem Code anzeigt. Davon handelt die Lektion über Formulare in Komponenten.

Sieh es dir an

Sieh, was bei „Jetzt bestellen“ passiert

Der Code ist ein kurzes Bestellformular. Achte auf die Reihenfolge: erst die Prüfung, dann das Ereignis, dann das Einsammeln.

<form action="/order" method="post">
<label>Name <input name="name" required></label>
<label>E-Mail <input name="email" type="email" required></label>
<label>Telefon <input name="phone" pattern="0[0-9]{9}"></label>
<label>Menge <input name="qty" type="number" min="1" max="10"></label>
<label><input name="gift" type="checkbox"> Geschenk</label>
<button>Jetzt bestellen</button>
</form>
Schritt für Schritt, in Worten
  1. Der Käufer klickt auf „Jetzt bestellen“. Der <button> hat kein type, also ist er in einem Formular ein Absende-Button. Der Browser sendet noch nichts.
  2. Zuerst prüft er jedes Feld in der Reihenfolge des Codes gegen seine Regeln. „iva“ ist keine E-Mail-Adresse, und „12345“ passt nicht zum Muster.
  3. Es gibt ungültige Felder, also tritt das Ereignis submit nicht ein. Der Browser fokussiert das erste ungültige Feld und zeigt nur dafür eine Meldung.
  4. Der Käufer korrigiert die E-Mail-Adresse und das Telefon und klickt noch einmal.
  5. Dieselbe Prüfung von oben. Diesmal besteht jedes Feld.
  6. Erst jetzt tritt das Ereignis submit ein. Wenn der Code es nicht aufhält, sendet der Browser das Formular mit der Methode aus method an die Adresse aus action.
  7. Er sammelt von jedem Feld mit einem name ein Paar name=value ein. Die nicht angekreuzte Checkbox wird gar nicht gesendet.
  8. Mit method="post" stehen die Paare im Body der Anfrage, verbunden mit &. Der Schlüssel ist das Attribut name, nicht der Text der Beschriftung.

Der Browser prüft alle Felder, zeigt aber nur für das erste ungültige eine Meldung. Darum korrigiert eine Käuferin manchmal ein Feld und sieht gleich eine Meldung für das nächste. Und gift wird gar nicht gesendet: Für den Server sind eine nicht angekreuzte Checkbox und ein fehlendes Feld dasselbe.

Probier es aus

Füge die Prüfungen hinzu

Die Schnellbestellung für das Brot lässt alles durch. Füge Prüfungen hinzu: Die Menge liegt zwischen 1 und 10, die E-Mail-Adresse ist Pflicht und muss eine E-Mail-Adresse sein, das Telefon ist Pflicht und besteht aus einer 0 und neun weiteren Ziffern. Die Prüfung tippt 12, eine leere E-Mail-Adresse, „iva“, ein leeres und ein falsches Telefon und erwartet, dass der Browser beim richtigen Feld stehen bleibt.

HTML, CSS, JS
index.html
Genauer, für Neugierige

Der Server prüft noch einmal. Die Prüfung im Browser ist eine Bequemlichkeit für die Käuferin: Sie sieht den Fehler sofort. Den Shop schützt sie nicht. novalidate, das Panel Elements oder eine Anfrage ohne Browser umgehen sie, darum prüft der Server jedes Feld noch einmal. Warum das so ist, steht in der Lektion „Nicht vertrauenswürdige Eingaben“.

Was nicht gesendet wird. Ein Feld ohne name, eine nicht angekreuzte Checkbox, ein nicht gewählter Radiobutton und ein Feld mit disabled. Ein Feld mit readonly wird gesendet: Es lässt sich nur nicht ändern. Dateien (type="file") brauchen method="post" und enctype="multipart/form-data".

Wie gesendet wird. Bei method="get" (dem Standard) landen die Paare in der Adresse: /order?name=…&phone=…. Bei method="post" stehen sie im Body der Anfrage. In beiden Fällen werden sie kodiert: @ wird zu %40, und ein Leerzeichen wird zu +.

Enter. Enter in einem Textfeld sendet das Formular wie ein Klick auf den Absende-Button, mit denselben Prüfungen.

minlength und ein Wert aus Code. minlength prüft nur Text, den ein Mensch getippt hat. Ein Wert aus dem Attribut value oder aus JavaScript besteht, auch wenn er kurz ist.

Ohne Prüfungen. formnovalidate an einem Button sendet ohne Prüfung (etwa bei „Entwurf speichern“). form.submit() aus JavaScript prüft ebenfalls nicht und löst das Ereignis submit nicht aus, während form.requestSubmit() alles tut, was ein Klick tut.

Fehler gestalten. CSS sieht ungültige Felder mit :invalid, und :user-invalid erfasst sie erst, nachdem ein Mensch sie berührt hat. So ist ein Feld nicht rot, bevor die Käuferin etwas getippt hat. Das nächste Modul handelt von CSS.

autocomplete. autocomplete="email", "tel", "name", "street-address" sagen dem Browser, was er aus dem Gespeicherten anbieten soll. Die Käuferin füllt die Bestellung mit zwei Klicks aus.

Übung

Das Bestellformular

Baue das Formular an der Kasse von Grund auf, mit den Feldern in dieser Reihenfolge. „Name“ (name), Pflicht. „E-Mail“ (email), eine Pflicht-E-Mail-Adresse. „Telefon“ (phone), Pflicht, eine 0 und neun weitere Ziffern. „Stadt“ (city): ein Dropdown Sofia, Plovdiv, Varna mit den Werten sofia, plovdiv, varna. Eine Gruppe „Lieferung“ mit zwei Radiobuttons (delivery): „An die Adresse“ (address), am Anfang gewählt, und „An eine Filiale“ (office). „Hinweis für den Kurier“ (note), über mehrere Zeilen. Eine Checkbox „Als Geschenk verpacken“ (gift) mit dem Wert yes. Ein Button „Jetzt bestellen“.

HTML, CSS, JS
index.html

Test

Teste dich

1. Die Käuferin hat „Anna“ in ein Feld <input id="name"> ohne name getippt. Was sendet das Formular?
2. Zwei Radiobuttons für die Lieferung haben name="courier" und name="office". Was passiert?
3. Das Feld ist <input name="email" type="email" required>, und die Käuferin hat anna getippt. Was tut der Browser bei „Jetzt bestellen“?
4. Warum prüft der Server die Bestellung, wenn der Browser sie schon geprüft hat?
5. Ein Formular hat <button>Code einlösen</button> ohne type. Was tut ein Klick darauf?

Erstellt von Ivo Gergov im Rahmen der Kampagne von Evo Tech für zugängliche Programmierausbildung ·