mitmario.dev

Was HTML schon prüft

JavaScript Im Browser 3 Min Lesezeit 3 BeispieleLektion 3 von 7

Wer ein Alter von 12 einträgt, wo 18 verlangt ist, soll das erfahren, bevor das Formular abgeschickt ist. Für die häufigsten Regeln braucht es dafür kein JavaScript, das Markup kann sie selbst, und der Code fragt sie nur noch ab.

Die Regeln im Markup

Was HTML schon kann
const protokoll = document.getElementById("protokoll");

for (const feld of document.querySelectorAll("input")) {
  // checkValidity fragt, ob das Feld nach den HTML-Regeln
  // in Ordnung ist. validationMessage ist der Text, den der
  // Browser dazu anzeigen würde, in der Sprache des Nutzers.
  const zeile = [
    feld.name,
    feld.checkValidity() ? "gültig" : "ungültig",
    feld.validationMessage || "keine Meldung",
  ].join(" | ");
  protokoll.textContent = `${protokoll.textContent}${zeile}\n`;
}

// validity sagt sogar, WORAN es lag.
const alter = document.getElementById("alter");
console.log("zu klein?", alter.validity.rangeUnderflow);
console.log("leer?", document.getElementById("name").validity.valueMissing);
console.log("Muster verfehlt?", document.getElementById("plz").validity.patternMismatch);

// Und für das ganze Formular auf einmal.
console.log("Formular gültig?", document.getElementById("formular").checkValidity());

Fünf Attribute decken die meisten Formulare ab.

  • required verlangt, dass das Feld nicht leer bleibt.
  • type="email" verlangt eine Adresse, type="number" eine Zahl.
  • min und max begrenzen eine Zahl, minlength und maxlength die Länge eines Textes.
  • pattern nimmt einen regulären Ausdruck aus Abschnitt 9.

Diese Regeln wirken ohne JavaScript, auf jedem Gerät, und ihre Meldungen kommen in der Sprache des Browsers, ohne dass jemand sie übersetzen muss. Der Typ tut nebenbei noch mehr, auf dem Telefon bringt type="email" eine Tastatur mit @ mit und type="number" eine mit Ziffern. Im ersten Beispiel sind alle vier Felder absichtlich falsch gefüllt. Ein Klick auf „Absenden“ schickt nichts ab, der Browser hält am ersten davon an und stellt seine eigene Blase daneben, ohne eine Zeile eigenen Code.

pattern und die Anker

pattern bringt die Anker mit
const plz = document.getElementById("plz");
const protokoll = document.getElementById("protokoll");

// Dasselbe Muster wie in Abschnitt 9, nur ohne ^ und $.
// Der Browser prüft trotzdem den ganzen Text.
for (const wert of ["04103", "041030", "PLZ 04103", ""]) {
  plz.value = wert;
  const zeile = `"${wert}" ist ${plz.checkValidity() ? "gültig" : "ungültig"}`;
  protokoll.textContent = `${protokoll.textContent}${zeile}\n`;
}

// Das leere Feld ist gültig, denn ohne required darf es leer
// bleiben. pattern prüft nur, was drinsteht.
console.log("required?", plz.required);

Ein Muster in pattern gilt immer für den ganzen Inhalt des Feldes. Der Browser setzt ^ und $ selbst, und pattern="[0-9]{5}" lässt deshalb 04103 durch, 041030 und PLZ 04103 aber nicht. Mit eigenen Ankern geht es auch, nur ändert sich dadurch nichts.

Das leere Feld im zweiten Beispiel ist gültig. pattern prüft nur, was drinsteht, und ob überhaupt etwas drinstehen muss, sagt allein required.

Dieselben Regeln aus JavaScript

  • feld.checkValidity() liefert true oder false.
  • feld.validationMessage ist der Text, den der Browser anzeigen würde.
  • feld.validity sagt, woran es lag, valueMissing, typeMismatch, rangeUnderflow, patternMismatch und einige mehr.
  • formular.checkValidity() fragt für alle Felder auf einmal.

In der Eingabezeile der Console antwortet alter.validity.rangeUnderflow im ersten Beispiel mit true, die 12 liegt unter 18. Nach alter.value = "30" antwortet alter.checkValidity() mit true, denn die Regeln aus dem Markup prüfen den Wert, der jetzt im Feld steht. alter.validity als Ganzes antwortet nur mit ValidityState {}, aus demselben Grund wie beim Ereignis in Abschnitt 12.

novalidate und eigene Worte

Eigene Worte für dieselben Regeln
const formular = document.getElementById("formular");

// Die Regeln bleiben im Markup. JavaScript fragt nur, welche
// verletzt ist, und sagt es in eigenen Worten.
function meldungFuer(feld) {
  const gueltigkeit = feld.validity;
  if (gueltigkeit.valueMissing) return "Das Feld ist leer";
  if (gueltigkeit.patternMismatch) return "Eine Postleitzahl hat fünf Ziffern";
  if (gueltigkeit.rangeOverflow) return `Höchstens ${feld.max}`;
  return "";
}

formular.addEventListener("submit", (event) => {
  // novalidate am Formular: der Browser hält nicht mehr an und
  // zeigt keine Blase. Die Regeln gelten trotzdem weiter.
  event.preventDefault();
  for (const feld of formular.querySelectorAll("input")) {
    document.getElementById(`fehler-${feld.id}`).textContent = meldungFuer(feld);
  }
  console.log("Formular gültig?", formular.checkValidity());
});

novalidate am Formular schaltet die Blasen ab. Die Regeln schaltet es nicht ab, checkValidity() und validity antworten weiter wie vorher, und ab hier ist der eigene Code für die Meldung zuständig.

Wer eigene Meldungen anzeigt, ergänzt die eingebaute Prüfung, statt sie wegzuwerfen. Die Attribute bleiben im Markup, denn sie beschreiben, was das Feld verlangt, und andere Werkzeuge lesen das aus. Das dritte Beispiel fragt validity nach dem Grund und schreibt ihn in eigenen Worten neben das Feld.

Für eine Adresse ist der Browser dabei großzügiger als das grobe Muster aus Abschnitt 9. ida@example gilt bei type="email" als gültig, auch ohne Punkt, denn auch eine Adresse in einem Firmennetz ohne Endung ist eine Adresse.

Was HTML nicht kennt, etwa ein Passwort, das mit einem zweiten übereinstimmen soll, braucht eine eigene Prüfung, und die kommt in der nächsten Lektion.

In der Aufgabe sagt eine Funktion für jedes Feld, welche Regel aus dem Markup verletzt ist, in eigenen Worten.

Zum Mitnehmen

required, type, min, max und pattern prüfen ein Feld ohne eine Zeile JavaScript, und pattern bringt seine Anker selbst mit. Aus dem Code fragt man dieselben Regeln über checkValidity und validity, und novalidate schaltet nur die Blasen des Browsers ab, nicht die Regeln.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

Was in dieser Lektion steckt

  • Artikel mit 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe im Editor, direkt im Browser geprüft

    Öffnet sich mit dem Basis Konto.