# Verzögerung beim Absenden oder doppelte Übermittlungen

> Formspree Docs · Fehlerbehebung · 11. April 2024

Wenn du jemals auf "Absenden" eines HTML-Formulars geklickt hast, hast du wahrscheinlich diesen Moment der Unsicherheit erlebt, der eintritt, bevor du zur "Danke"-Seite weitergeleitet wirst. Auch wenn er nur wenige Augenblicke dauert, kann er viele Fragen aufwerfen, etwa "Funktioniert das Formular nicht?", "Wurde mein Klick registriert?" oder sogar "Ist das Internet ausgefallen?". Manchmal klicken Nutzer aus Panik erneut auf den Absenden-Button, was zu doppelten Übermittlungen führt.

Die Verzögerung sorgt für ein unangenehmes Nutzererlebnis. Hinzu kommt, dass ein zweiter Klick eine doppelte Anfrage an dein Formspree-Formular auslöst (die auf dein Nutzungskontingent angerechnet wird) sowie einen doppelten Eintrag in deiner Übermittlungsliste (den du später bereinigen musst). Deshalb haben wir diese kurze Anleitung zusammengestellt, die dir helfen soll zu verstehen, warum das passiert und wie du es mit einem kurzen JS-Snippet beheben kannst.

## **Warum passiert das?**

Die Verzögerung, die deine Nutzer nach dem Klick auf den "Absenden"-Button eines Formspree-Formulars erleben, wird nicht durch ein Problem mit Formspree selbst verursacht; sie ist ein natürliches Resultat der Funktionsweise von Webformularen. Hier ein kurzer Überblick über den Ablauf: Wenn ein Nutzer auf den "Absenden"-Button klickt, initiiert der Browser eine HTTP-Anfrage an das Backend mit den Formulardaten. Diese Anfrage reist durch das Internet, um das Backend zu erreichen, wobei es aufgrund langsamer Netzwerkverbindungen zu Latenz kommen kann.

Sobald die Anfrage die Server erreicht, muss sie verarbeitet werden. Das kann die Validierung der Informationen, das Speichern in der Datenbank und möglicherweise das Versenden von Bestätigungs-E-Mails umfassen. Auch diese Verarbeitung benötigt Zeit, allerdings in der Regel weniger als die Netzwerkübertragung. Sobald sie abgeschlossen ist, antwortet das Backend mit einer Bestätigung und leitet den Nutzer zur "Danke"-Seite weiter.

Die Zeit, die die Anfrage für den Weg zum Server und zurück benötigt, verursacht eine Verzögerung auf Seiten des Nutzers nach dem Klick auf den "Absenden"-Button. Außerdem können langsamere Verbindungen wie Mobilfunknetze die Latenz der Anfrage erhöhen und das Problem verschärfen.

So sieht die Verzögerung aus:

![9Yt3xqi.gif](/images/zendesk/55d2857f77082f83.gif)

## **Wie kannst du das beheben?**

Auch wenn du nichts gegen die Zeit unternehmen kannst, die während der HTTP-Anfrage vergeht, kannst du dennoch ein besseres Warteerlebnis für deine Nutzer schaffen. Wenn du ein React-basiertes (oder Next/Gatsby-basiertes) Projekt entwickelst, kannst du das `state`-Objekt nutzen, das vom `useForm`-Hook der [Formspree-React-Bibliothek](/articles/working-with-react/the-formspree-react-library/) zurückgegeben wird, um zu erfahren, ob das Formular gerade übermittelt wird, und den Absenden-Button zu deaktivieren. In reinem JS musst du diese Prüfung jedoch selbst implementieren.

Dazu musst du auf das [Formular-Submit-Event](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event) lauschen, das jedes Mal ausgelöst wird, wenn ein Formular auf einer Webseite übermittelt wird. Sobald du dieses Event erhältst, musst du den Absenden-Button deaktivieren und/oder ein UI-Element (etwa einen Spinner) anzeigen, das den Nutzer darüber informiert, dass die Formulardaten im Hintergrund verarbeitet werden.

> HINWEIS: Du könntest dieselbe Logik zwar auch mit einem [Click-Event](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event) auf dem "Absenden"-Button umsetzen, doch das "submit"-Event des Formulars ist eine zuverlässigere Methode, um alle möglichen Wege der Formularübermittlung zu erfassen, dazu gehören das Klicken auf den "Absenden"-Button, das Drücken von `Enter` beim Bearbeiten eines Feldes und das programmatische Absenden des Formulars durch Aufruf der Methode `form.requestSubmit()`.

### **Den Button beim Absenden deaktivieren**

Der einfachste Weg, den Nutzer über die Hintergrundverarbeitung zu informieren, besteht darin, den Absenden-Button zu deaktivieren und optional beim Überfahren des Buttons ein Warte-Symbol am Cursor anzuzeigen. So würde das aussehen:

![VueV1eF.gif](/images/zendesk/04905806e773197c.gif)

Um das umzusetzen, musst du per CSS einen ausgegrauten Hintergrund und den `wait`-Cursor für den deaktivierten Zustand des Buttons festlegen. Anschließend musst du auf das `submit`-Event des HTML-Formulars lauschen und das `disabled`-Attribut des Absenden-Buttons auf `true` setzen, sobald das `submit`-Event beobachtet wird.

So würde die HTML-Datei aussehen:

```html
<html>

<head>
    <style>
        /* Other styles omitted... */
        
        /* 1. Set the background and cursor for the disabled state of the button */
        #submitButton:disabled {
            cursor: wait;
            background: #dfdfdf;
        }

    </style>
</head>

<body>
    <form id="contact-form" name="simple-contact-form" accept-charset="utf-8" action="https://formspree.io/f/{form_id}"
        method="post">
        <label for="full-name">Full Name</label>
        <input type="text" name="name" id="full-name" placeholder="First and Last" required="">
        <label for="email-address">Email Address</label>
        <input type="email" name="_replyto" id="email-address" placeholder="email@domain.tld" required="">
        <label for="message">Message</label>
        <textarea rows="5" name="message" id="message"
            placeholder="Your message here"
            required=""></textarea>
        <input id="submitButton" type="submit" value="Submit">
    </form>

    <!-- 2. Add the following script to listen to the submit event -->
    <script>
        const form = document.getElementById('contact-form');
        const submitButton = document.getElementById('submitButton');
	
	
        form.addEventListener('submit', function (event) {
	
            // Sets the submit button's disabled attribute as true
            submitButton.disabled = true;
        });
    </script>
</body>

</html>
```

Diese Methode ist unkompliziert und übernimmt die nativen Cursor-Lader plattformübergreifend. Hier ist zum Beispiel, wie der Lade-Cursor für einen Windows-Nutzer aussehen würde:

![mUg5eOm.gif](/images/zendesk/ecc14008d606e832.gif)

Auf Mobilgeräten ist der Cursor nicht sichtbar. Der Absenden-Button ist jedoch weiterhin ausgegraut, sodass der Nutzer weiß, dass sein Tippen registriert wurde und er kein zweites Mal tippen kann:

![fU5hbNa.gif](/images/zendesk/221f83b7ee10da1b.gif)

### **Den Button beim Absenden durch ein anderes UI-Element ersetzen**

Alternativ könntest du den Absenden-Button vollständig ausblenden und an seiner Stelle ein UI-Element wie einen Spinner anzeigen, wenn ein Formular übermittelt wird:

![Vi8x3Oc.gif](/images/zendesk/0fa8ce7db3c32b21.gif)

Der Code für dieses Formular ist ebenfalls recht unkompliziert:

```html
<html>

<head>
    <style>
        /* 1. Add the following styles */
        #loader-container {
            width: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }

        #loader {
            border: 4px solid #e5122e; 
            border-bottom: 4px solid #fff;
            border-radius: 50%;
            width: 16px;
            height: 16px;
            animation: spin 1s linear infinite;
        }
          
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
    </style>
</head>

<body>
    <form id="contact-form" name="simple-contact-form" accept-charset="utf-8" action="<https://formspree.io/f/{form_id}>"
        method="post">
        <fieldset id="fs-frm-inputs">
            <div id="inputs">
                <label for="full-name">Full Name</label>
                <input type="text" name="name" id="full-name" placeholder="First and Last" required="">
                <label for="email-address">Email Address</label>
                <input type="email" name="_replyto" id="email-address" placeholder="email@domain.tld" required="">
                <label for="message">Message</label>
                <textarea rows="5" name="message" id="message"
                    placeholder="Your message here"
                    required=""></textarea>
                <input type="hidden" name="_subject" id="email-subject" value="Contact Form Submission">
            </div>
        </fieldset>
        <input id="submitButton" type="submit" value="Submit">
        
        <!-- 2. Add the following div tags -->
        <div id="loader-container" >
            <div id="loader" hidden="hidden"></div>
        </div>
        
    </form>

	<!-- 3. Add the following script to listen to the submit event -->
	<script>
	    const form = document.getElementById('contact-form');
	    const submitButton = document.getElementById('submitButton');
	    const loader = document.getElementById('loader')
	
	
	    form.addEventListener('submit', function (event) {
	    
	        // Removes the hidden attribute from the loader element
	        loader.hidden = ""
	        
	        // Sets the submit button to be hidden
	        submitButton.hidden = "hidden";
	    });
	</script>
</body>

</html>
```

Du fügst zwei `<div>`s hinzu, eines im anderen verschachtelt, direkt unter dem Absenden-Button, ergänzt das CSS, um den Loader im Container zu zentrieren, und richtest Keyframes für die Animation des Loaders ein. Schließlich fügst du das JS-Skript hinzu, das auf das Formular-Submit-Event lauscht und den Absenden-Button ausblendet, während der Loader eingeblendet wird.

Dieser Ansatz gibt dir mehr Kontrolle über das UI-Design des Loader-Elements. Außerdem kannst du ein einheitliches Design für deinen Loader über alle Plattformen hinweg beibehalten.

> Das Skript zum Hinzufügen des Formular-Submit-Event-Listeners muss auf das HTML-DOM zugreifen, um den Event-Listener einzurichten. Daher musst du sicherstellen, dass der Code zum Hinzufügen des Formular-Submit-Event-Listeners `(form.addEventListener('submit', function (event) {})` erst ausgeführt wird, nachdem das DOM fertig geladen ist. Das bedeutet: Wenn du ein Inline-Skript verwendest, achte darauf, es direkt vor dem schließenden `</body>`-Tag einzufügen, genau wie in den oben gezeigten Beispielen. Wenn du alternativ ein externes Skript verwendest, stelle sicher, dass du entweder seine Ausführung mit dem defer-Attribut im `<script>`-Tag bis nach dem Parsen des HTML-DOM `defer`st oder im Skript auf das `DOMContentLoaded`-Event lauschst, bevor du den Formular-Submit-Event-Listener zum Dokument hinzufügst.

## **Ein reibungsloses UX mit deinen Formularen bieten**

Wie du gesehen hast, lassen sich das Problem der Verzögerung beim Feedback nach dem Klick auf den Absenden-Button und Vorfälle mit doppelten Übermittlungen leicht beheben, indem du UI-Elemente implementierst, die den Nutzer über die im Hintergrund laufende Verarbeitung seiner Formularübermittlung informieren. Hoffentlich hat dir diese Anleitung geholfen zu verstehen, wie es hinter den Kulissen funktioniert, und dir einige nützliche Code-Snippets an die Hand gegeben, mit denen du sofort loslegen kannst.
