Wie du HTML-Formulardaten mit JavaScript fetch() sendest

HTML form submit fetch javascript tutorial showing code editor with fetch API call and form submission flow

Falls du schon einmal ein Kontaktformular erstellt hast und dabei zugesehen hast, wie die gesamte Seite nach einem Klick auf "Absenden" neu lädt, kennst du bereits dieses unangenehme Nutzererlebnis. Mit HTML Formular absenden fetch JavaScript Techniken kannst du Formulardaten im Hintergrund an einen Backend-Endpunkt senden, den Nutzer auf derselben Seite behalten und eine saubere Erfolgs- oder Fehlermeldung ohne vollständiges Neuladen der Seite anzeigen. Dieses Tutorial führt dich durch jeden Schritt - vom Schreiben des grundlegenden HTML bis hin zur Verknüpfung deines fetch()-Aufrufs mit einem Sendform-Endpunkt, sodass deine Übermittlungen direkt in deinem Posteingang oder verbundenen Workflow landen.

Wichtigste Erkenntnisse:

  • Die Fetch API ermöglicht es, Formulardaten ohne Seitenneuladung zu übermitteln und bietet Nutzern eine flüssigere Erfahrung.
  • Das Abfangen des submit-Events und der Aufruf von preventDefault() bilden das Fundament jedes Ajax-Formular-Übermittlungsmusters.
  • Sendform stellt eine fertige Endpunkt-URL bereit, sodass du null Backend-Code benötigst, um Übermittlungen zu empfangen und zu speichern.
  • Die ordnungsgemäße Antwortbehandlung (Anzeige von Erfolgs- oder Fehlermeldungen) ist genauso wichtig wie das korrekte Senden der Daten.

Warum fetch() statt Standard-Formularübermittlung verwenden

Das Standard-Formularübermittlungsverhalten des Browsers macht genau eine Sache: Es serialisiert die Formularfelder, sendet eine POST- (oder GET-) Anfrage an die action-URL und lädt dann die Antwort des Servers. Das bedeutet, der Nutzer sieht ein weißes Aufblitzen, verliert seine Scroll-Position und wartet darauf, dass eine neue Seite gerendert wird. Bei einer langsamen Verbindung kann sich das kaputt anfühlen.

Die Fetch API löst dies, indem sie HTTP-Anfragen programmatisch und vollständig in JavaScript durchführt, ohne wegzunavigieren. Dies ermöglicht ein Formular absenden ohne Seitenneuladung Muster, das Nutzer bei der Stange hält und dir vollständige Kontrolle über alle Aspekte der Nutzererfahrung gibt, einschließlich Ladezustände, Inline-Validierungsrückmeldungen und animierte Erfolgsbanner.

Weitere praktische Gründe, fetch() zu bevorzugen:

  • Du kannst benutzerdefinierte Header anhängen (zum Beispiel einen CSRF-Token oder einen Autorisierungsschlüssel), die ein einfaches HTML-Formular nicht senden kann.
  • Du kannst Daten als JSON, FormData oder URL-kodierte Strings serialisieren, je nachdem was der Endpunkt erwartet.
  • Die Fehlerbehandlung ist explizit. Du entscheidest, was "Fehler" bedeutet und wie du es kommunizierst.
  • Es funktioniert auf jeder statischen Website, einschließlich solcher, die auf GitHub Pages, Netlify oder einem CDN gehostet werden, da die Logik vollständig im Browser lebt.

Hinweis: Falls du mit einem Website-Builder wie Webflow, WordPress oder Hugo arbeitest, gilt derselbe fetch()-Ansatz. Siehe unseren Leitfaden zur Integration von Sendform mit deinem Website-Builder für plattformspezifische Tipps.

Das grundlegende HTML-Formular Setup

Bevor du eine einzige Zeile JavaScript schreibst, brauchst du ein gut strukturiertes HTML-Formular. Das wichtige Detail hier ist, dass du kein action-Attribut benötigst, das irgendwohin zeigt, da JavaScript die Übermittlung übernehmen wird. Du möchtest jedoch aussagekräftige name-Attribute bei jedem Input - diese werden zu den Feldschlüsseln in der übermittelten Nutzlast.

<form id="contact-form" novalidate>
  <div>
    <label for="name">Dein Name</label>
    <input type="text" id="name" name="name" required placeholder="Maria Müller">
  </div>

  <div>
    <label for="email">E-Mail-Adresse</label>
    <input type="email" id="email" name="email" required placeholder="[email protected]">
  </div>

  <div>
    <label for="message">Nachricht</label>
    <textarea id="message" name="message" rows="5" required></textarea>
  </div>

  <button type="submit">Nachricht senden</button>

  <!-- Feedback-Bereich -->
  <div id="form-feedback" aria-live="polite"></div>
</form>

Ein paar erwähnenswerte Dinge in diesem Markup:

  • novalidate am Formularelement deaktiviert native Browser-Validierungshinweise und gibt dir vollständige Kontrolle über Fehlermeldungen in JavaScript.
  • Das id="form-feedback" div mit aria-live="polite" ist der Ort, wo Erfolgs- und Fehlermeldungen erscheinen werden. Das ARIA-Attribut stellt sicher, dass Screenreader das Feedback automatisch ansagen.
  • Jeder Input hat sowohl eine id (für die Label-Zuordnung) als auch einen name (für die Formular-Nutzlast).

Das Submit-Event abfangen

Der erste Schritt bei jeder JavaScript Formularübermittlung ist das Abfangen des Standard-Browser-Verhaltens. Du machst das, indem du auf das submit-Event am Formularelement hörst und sofort event.preventDefault() aufrufst.

const form = document.getElementById('contact-form');

form.addEventListener('submit', async function (event) {
  event.preventDefault(); // Stoppe die Standard-Seitennavigation

  // Grundlegende clientseitige Validierung
  const name = form.elements['name'].value.trim();
  const email = form.elements['email'].value.trim();
  const message = form.elements['message'].value.trim();

  if (!name || !email || !message) {
    showFeedback('Bitte fülle alle Felder aus.', 'error');
    return;
  }

  // Fahre mit dem Senden der Daten fort (nächster Abschnitt)
  await submitForm({ name, email, message });
});

Indem du die Validierungslogik vom Netzwerkaufruf trennst, hältst du den Code lesbar und einfach erweiterbar. Das async-Schlüsselwort am Event-Handler ermöglicht es dir, await darin zu verwenden, was den Fetch API Formulardaten-Aufruf synchron aussehen lässt und tief verschachtelte Promise-Ketten vermeidet.

fetch() auf einen Sendform-Endpunkt ausrichten

Hier passiert die eigentliche Arbeit. Anstatt deinen eigenen Server zu erstellen, um Formularübermittlungen zu empfangen, zu speichern und weiterzuleiten, kannst du Sendform als dein Backend verwenden. Nachdem du ein Formular im Sendform-Dashboard erstellt hast, erhältst du eine eindeutige Endpunkt-URL. Diese URL ist alles, was du brauchst.

Die folgende Übermittlungsfunktion verwendet die FormData API, um die Nutzlast zu erstellen, die Sendform nativ akzeptiert:

async function submitForm(data) {
  // Ersetze diese URL mit deinem tatsächlichen Sendform-Endpunkt
  const SENDFORM_ENDPOINT = 'https://sendform.net/de/YOUR_FORM_ID';

  const formData = new FormData();
  formData.append('name', data.name);
  formData.append('email', data.email);
  formData.append('message', data.message);

  try {
    const response = await fetch(SENDFORM_ENDPOINT, {
      method: 'POST',
      body: formData,
    });

    if (response.ok) {
      showFeedback('Vielen Dank! Deine Nachricht wurde gesendet.', 'success');
      form.reset();
    } else {
      const errorData = await response.json().catch(() => ({}));
      const errorMsg = errorData.message || 'Etwas ist schief gelaufen. Bitte versuche es erneut.';
      showFeedback(errorMsg, 'error');
    }
  } catch (networkError) {
    showFeedback('Netzwerkfehler. Überprüfe deine Verbindung und versuche es erneut.', 'error');
  }
}

Wichtige Entscheidungen in diesem Code:

  • Kein Content-Type-Header wird manuell gesetzt. Wenn du ein FormData-Objekt als Body übergibst, setzt der Browser automatisch die korrekte multipart/form-data-Grenze.
  • Die response.ok-Prüfung deckt alle 2xx HTTP-Statuscodes ab, nicht nur 200. Das ist robuster als response.status === 200 zu vergleichen.
  • Das äußere try/catch fängt Netzwerk-Level-Fehler ab (DNS-Fehler, Offline-Status), die response.ok nie sehen würde.
JavaScript fetch Formularübermittlungsablauf, der auf eine Sendform-Endpunkt-URL zeigt

Die Antwort behandeln - Erfolgs- und Fehlermeldungen

Das Senden der Daten ist nur die halbe Arbeit. Nutzer brauchen sofortiges, klares Feedback. Die oben referenzierte showFeedback()-Hilfsfunktion schreibt eine Nachricht in das Feedback-div, das du zum HTML hinzugefügt hast:

function showFeedback(message, type) {
  const feedbackEl = document.getElementById('form-feedback');
  feedbackEl.textContent = message;
  feedbackEl.className = type === 'success' ? 'feedback-success' : 'feedback-error';
}

Das ist absichtlich minimal gehalten. In einem echten Projekt könntest du textContent gegen eine animierte Komponente oder eine Toast-Benachrichtigungsbibliothek austauschen, aber das Muster bleibt dasselbe: Aktualisiere das DOM basierend auf dem Ergebnis des fetch()-Aufrufs.

Für erweiterte Szenarien, wie die Weiterleitung zu einer benutzerdefinierten Dankesseite oder das Auslösen einer nachgelagerten Automatisierung nach der Übermittlung, sieh dir unseren Artikel über die Automatisierung von Formular-Workflows mit Webhooks, Zapier und APIs an.

Best Practices und Tipps

Den Code zum Laufen zu bringen ist eine Sache. Ihn so auszuliefern, dass er in der Produktion standhält, ist eine andere. Hier sind die wichtigsten Tipps, die du beachten solltest:

  • Deaktiviere den Submit-Button während der Anfrage. Setze button.disabled = true bevor du fetch() aufrufst und aktiviere ihn in einem finally-Block wieder. Das verhindert doppelte Übermittlungen, wenn der Nutzer mehrmals klickt.
  • Zeige einen Ladezustand. Ändere den Button-Text zu "Wird gesendet..." oder füge eine Spinner-Klasse hinzu, während die Anfrage läuft. Nutzer, die kein Feedback sehen, nehmen oft an, dass nichts passiert ist und klicken erneut.
  • Validiere auch serverseitig. Clientseitige Validierung ist für die Nutzererfahrung. Sendform und jeder Backend-Service sollten alle eingehenden Daten als nicht vertrauenswürdig behandeln.
  • Verwende überall HTTPS. Das Senden von Formulardaten über einfaches HTTP exponiert Nutzereingaben während der Übertragung. Sendform-Endpunkte sind standardmäßig HTTPS, aber stelle sicher, dass auch deine eigene Seite über HTTPS ausgeliefert wird.
  • Füge Spam-Schutz hinzu. Ein Honeypot-Feld oder eine CAPTCHA-Integration reduziert Junk-Übermittlungen erheblich. Für einen tieferen Einblick in dieses Thema, siehe unseren Leitfaden zu Best Practices für Spam-Schutz bei Formularen.
  • Teste den Fehlerfall bewusst. Ändere vorübergehend die Endpunkt-URL zu etwas Ungültigem und bestätige, dass deine Fehlermeldung erscheint. Die meisten Entwickler testen nur den Happy Path.
  • Halte die Endpunkt-URL aus der Versionskontrolle heraus. Falls dein Projekt Open Source ist, speichere den Sendform-Endpunkt in einer Umgebungsvariable oder einer Konfigurationsdatei, die in .gitignore aufgelistet ist.

Nutzer statischer Websites: Falls dein Projekt eine Hugo-, Eleventy- oder einfache HTML-Website ohne Server ist, ist der hier beschriebene fetch()-Ansatz die empfohlene Methode. Lies mehr in unserem Leitfaden zur serverlosen Formularverarbeitung für statische Websites.

Fazit

Das Ersetzen einer Standard-Formularübermittlung durch einen fetch()-Aufruf ist eine der wirkungsvollsten Verbesserungen, die du an jedem Kontakt- oder Lead-Erfassungsformular vornehmen kannst. Das Ergebnis ist eine schnellere, professionellere Erfahrung, die Nutzer auf deiner Seite hält und dir vollständige Kontrolle über Feedback-Nachrichten gibt. Kombiniere das mit einem Sendform-Endpunkt und du eliminierst die Notwendigkeit für jeglichen serverseitigen Code vollständig. Dein Formular ist live, deine Übermittlungen erreichen deinen Posteingang und deine Nutzer sehen nie ein störendes Seitenneuladung. Erstelle noch heute deinen kostenlosen Sendform-Endpunkt und lass deine erste Übermittlung in wenigen Minuten zustellen.

Häufig gestellte Fragen

Ja. Da fetch() vollständig im Browser läuft, funktioniert es auf statischen HTML-Websites, JAMstack-Projekten und jeder Plattform, die HTML ausliefert. Du benötigst keinen eigenen Server. Die einzige Anforderung ist ein Endpunkt (wie eine Sendform-URL), der die POST-Anfrage empfangen kann.

fetch() ist der moderne Ersatz für XMLHttpRequest. Es verwendet Promises, unterstützt async/await und hat eine sauberere API. Für neue Projekte ist fetch() immer zu bevorzugen. Beide erreichen dasselbe Ajax-Formular-Übermittlungsergebnis, aber fetch() benötigt deutlich weniger Boilerplate-Code.

Nein. Wenn du ein FormData-Objekt als body übergibst, setzt der Browser automatisch den Content-Type auf multipart/form-data und fügt den korrekten Boundary-String hinzu. Das manuelle Setzen würde die Anfrage tatsächlich kaputt machen, da dieser Boundary-Wert fehlen würde.

Melde dich bei Sendform an, erstelle ein neues Formular im Dashboard und kopiere die generierte Endpunkt-URL. Füge diese URL als Ziel in deinen fetch()-Aufruf ein. Übermittlungen werden sofort an deine konfigurierte E-Mail-Adresse weitergeleitet.

Ein Netzwerkfehler führt dazu, dass das fetch()-Promise abgelehnt wird, was vom äußeren try/catch-Block im Beispielcode abgefangen wird. Der Nutzer sieht die "Netzwerkfehler"-Nachricht, die du definiert hast. Die Übermittlung wird nicht automatisch in die Warteschlange eingereiht; der Nutzer muss es erneut versuchen, sobald die Verbindung wiederhergestellt ist.