Formularvalidierung – Teil 4: Validierung des MailChimp-Anmelde Formulars

Avatar of Chris Ferdinandi
Chris Ferdinandi am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

In den letzten Artikeln dieser Reihe haben wir gelernt, wie man eine Handvoll Eingabetypen und Validierungsattribute verwendet, um Formulare nativ zu validieren.

Wir haben gelernt, wie die Constraint Validation API verwendet wird, um den nativen Browser-Validierungsprozess für eine bessere Benutzererfahrung zu verbessern. Und wir haben ein Polyfill geschrieben, um die Unterstützung bis zurück zu IE9 zu erweitern (und einige Lücken in neueren Versionen zu schließen).

Lasst uns nun das Gelernte auf ein reales Beispiel anwenden: das MailChimp-Anmeldeformular.

Artikelserie

  1. Constraint-Validierung in HTML
  2. Die Constraint Validation API in JavaScript
  3. Ein Validity State API Polyfill
  4. Validierung des MailChimp-Anmeldeformulars (Sie sind hier!)

Ein einfaches Formular mit großer Wirkung

Wenn Sie ein MailChimp-Anmeldeformular auf Ihrer Website einbetten, wird es mit einem JavaScript-Validierungsskript namens `mc-validate.js` geliefert.

Diese Datei ist 140 KB (minifiziert) groß und enthält die gesamte jQuery-Bibliothek, zwei Plugins von Drittanbietern und benutzerdefinierten MailChimp-Code. Wir können das besser!

Den Ballast entfernen

Zuerst holen wir uns ein MailChimp-Formular ohne jeglichen Ballast.

Klicken Sie in MailChimp, wo Sie den Code für Ihr einbettbares Formular erhalten, auf den Tab "Naked". Diese Version enthält weder die MailChimp-CSS noch die MailChimp-JavaScript.

<div id="mc_embed_signup">
    <form action="//us1.list-manage.com/subscribe/post?u=12345abcdef&id=abc123" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
        <div id="mc_embed_signup_scroll">
            <h2>Subscribe to our mailing list</h2>
            <div class="indicates-required"><span class="asterisk">*</span> indicates required</div>
            <div class="mc-field-group">
                <label for="mce-FNAME">First Name </label>
                <input type="text" value="" name="FNAME" class="" id="mce-FNAME">
            </div>
            <div class="mc-field-group">
                <label for="mce-EMAIL">Email Address  <span class="asterisk">*</span></label>
                <input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL">
            </div>
                <div id="mce-responses" class="clear">
                    <div class="response" id="mce-error-response" style="display:none"></div>
                    <div class="response" id="mce-success-response" style="display:none"></div>
                </div>    <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
                <div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_f2d244c0df42a0431bd08ddea_aeaa9dd034" tabindex="-1" value=""></div>
                <div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
        </div>
    </form>
</div>

Das ist besser, aber es enthält immer noch etwas Markup, das wir nicht brauchen. Lasst es uns so weit wie möglich kürzen.

  1. Wir können den `div#mc_embed_signup`-Wrapper um das Formular herum entfernen.
  2. Ebenso können wir den `div#mc_embed_signup_scroll`-Wrapper um die Felder innerhalb des Formulars entfernen.
  3. Wir können auch den Text entfernen, der die Besucher darüber informiert, dass „* erforderlich ist.“
  4. Lasst uns die `.mc-field-group`-Klassen um unsere Formularfelder und die leeren `class`-Attribute auf den Feldern selbst entfernen.
  5. Wir sollten auch die Klassen `.required` und `.email` von unserem E-Mail-Feld entfernen, da diese nur als Haken für das MailChimp-Validierungsskript verwendet wurden.
  6. Ich habe das `*` aus dem E-Mail-Label entfernt. Es liegt ganz bei Ihnen, wie Sie erforderliche Felder beschriften möchten.
  7. Wir können den `div#mce-responses`-Container löschen, der nur von der MailChimp-JavaScript-Datei verwendet wird.
  8. Wir können auch die Klasse `.clear` aus dem `div` um den Submit-Button entfernen.
  9. Lasst uns alle leeren `value`-Attribute entfernen.
  10. Schließlich sollten wir das `novalidate`-Attribut aus dem `form`-Element entfernen. Das werden wir unser Skript hinzufügen lassen, wenn es geladen wird.

Das alles hinterlässt uns mit einem viel saubereren und bescheidener aussehenden Formular. Da die MailChimp-CSS entfernt wurde, übernimmt es die Standard-Formularstile Ihrer Website.

<form action="//us1.list-manage.com/subscribe/post?u=12345abcdef&id=abc123" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank">
    <h2>Subscribe to our mailing list</h2>
    <div>
        <label for="mce-FNAME">First Name</label>
        <input type="text" name="FNAME" id="mce-FNAME">
    </div>
    <div>
        <label for="mce-EMAIL">Email Address</label>
        <input type="email" name="EMAIL" id="mce-EMAIL">
    </div>
    <div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_f2d244c0df42a0431bd08ddea_aeaa9dd034" tabindex="-1" value=""></div>
    <div><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
</form>

Constraint Validation hinzufügen

Nun fügen wir einige Eingabetypen und Validierungsattribute hinzu, damit der Browser das Formular nativ validieren kann.

Der `type` für das E-Mail-Feld ist bereits auf `email` gesetzt, was großartig ist. Fügen wir auch das `required`-Attribut und ein `pattern` hinzu, um E-Mails zu zwingen, eine TLD (den `.com`-Teil einer Adresse) zu enthalten. Wir sollten auch einen `title` einfügen, der die Leute darüber informiert, dass sie eine TLD haben müssen.

Abonnieren Sie unseren Newsletter

Verbesserung mit der Constraint Validation API

Dies ist ein guter Anfang, aber wir können die Benutzererfahrung verbessern, indem wir das Formularvalidierungsskript hinzufügen, das wir bereits in dieser Serie geschrieben haben.

Unser Validierungsskript ist nur 6,7 KB *vor* Minifizierung, was es 20x kleiner macht als das, das MailChimp bereitstellt. Wenn wir die Unterstützung bis IE9 gewährleisten wollen, sollten wir jedoch unser Validity State Polyfill und Eli Greys classList.js Polyfill einbeziehen.

Das erhöht unsere Gesamtdateigröße auf 15,5 KB unminifiziert – immer noch 9x kleiner als das MailChimp-Validierungsskript.

Formular mit Ajax übermitteln

Das von MailChimp bereitgestellte Skript `mc-validate.js` validiert das Formular nicht nur. Es übermittelt es auch per Ajax und zeigt eine Statusmeldung an.

Wenn Sie auf unserer modifizierten Formular auf Senden klicken, wird der Besucher zur MailChimp-Website weitergeleitet. Das ist eine völlig legitime Vorgehensweise.

Wir können jedoch die Ajax-Formularübermittlung von MailChimp ohne jQuery nachbilden, um eine bessere Benutzererfahrung zu erzielen.

Das erste, was wir tun wollen, ist zu verhindern, dass das Formular wie üblich durch einen Seiten-Reload übermittelt wird. In unserem `submit`-Event-Listener rufen wir `event.preventDefault` auf, wenn Fehler vorliegen. Stattdessen rufen wir es immer auf.

// Check all fields on submit
document.addEventListener('submit', function (event) {

    // Only run on forms flagged for validation
    if (!event.target.classList.contains('validate')) return;

    // Prevent form from submitting
    event.preventDefault();

    ...

}, false);

JSONP verwenden

Das `mc-validate.js`-Skript verwendet JSONP, um Sicherheitsprobleme bei Cross-Domain-Anfragen zu umgehen.

JSONP funktioniert, indem die zurückgegebenen Daten als Skriptelement im `document` geladen werden, das dann diese Daten an eine Callback-Funktion übergibt, die die eigentliche Arbeit leistet.

Unsere Submit-URL einrichten

Zuerst richten wir eine Funktion ein, die wir ausführen können, wenn unser Formular bereit zur Übermittlung ist, und rufen sie in unserem `submit`-Event-Listener auf.

// Submit the form
var submitMailChimpForm = function (form) {
    // Code goes here...
};

// Check all fields on submit
document.addEventListener('submit', function (event) {

    ...

    // Otherwise, let the form submit normally
    // You could also bolt in an Ajax form submit process here
    submitMailChimpForm(event.target);

}, false);

Das Erste, was wir tun müssen, ist, die URL aus dem `action`-Attribut des Formulars zu holen.

// Submit the form
var submitMailChimpForm = function (form) {

    // Get the Submit URL
    var url = form.getAttribute('action');

};

Im Skript `mc-validate.js` wird `/post?u='` in der URL durch `/post-json?u=` ersetzt. Das können wir ganz einfach mit der `replace()`-Methode machen.

// Submit the form
var submitMailChimpForm = function (form) {

    // Get the Submit URL
    var url = form.getAttribute('action');
    url = url.replace('/post?u=', '/post-json?u=');

};

Unsere Formulardaten serialisieren

Als Nächstes möchten wir alle Formulardaten erfassen und daraus eine Query-Zeichenkette aus Schlüssel/Wert-Paaren erstellen. Zum Beispiel: `FNAME=Freddie%20Chimp&[email protected]`.

Lasst uns eine weitere Funktion erstellen, um dies für uns zu erledigen.

// Serialize the form data into a query string
var serialize = function (form) {
    // Code goes here...
};

Nun möchten wir alle Formularfelder durchlaufen und Schlüssel/Wert-Paare erstellen. Ich werde hier auf der Arbeit von Simon Steinberger aufbauen.

Zuerst erstellen wir eine `serialized`-Variable, die auf einen leeren String gesetzt ist.

// Serialize the form data into a query string
// Forked and modified from https://stackoverflow.com/a/30153391/1293256
var serialize = function (form) {

    // Setup our serialized data
    var serialized = '';

};

Nun holen wir uns alle Felder in unserem Formular mit `form.elements` und durchlaufen sie.
Wenn das Feld keinen Namen hat, ein Submit- oder Button-Element ist, deaktiviert ist oder ein Datei- oder Reset-Input ist, überspringen wir es.

Wenn es kein `checkbox` oder `radio` ist (ein schöner Sammelbegriff für `select`, `textarea` und die verschiedenen `input`-Typen) oder wenn es das ist und angehakt ist, konvertieren wir es in ein Schlüssel/Wert-Paar, fügen ein `&` am Anfang hinzu und hängen es an unseren `serialized`-String an. Wir stellen auch sicher, dass der Schlüssel und der Wert für die Verwendung in einer URL kodiert werden.

Schließlich geben wir den serialisierten String zurück.

// Serialize the form data into a query string
// Forked and modified from https://stackoverflow.com/a/30153391/1293256
var serialize = function (form) {

    // Setup our serialized data
    var serialized = '';

    // Loop through each field in the form
    for (i = 0; i < form.elements.length; i++) {

        var field = form.elements[i];

        // Don't serialize fields without a name, submits, buttons, file and reset inputs, and disabled fields
        if (!field.name || field.disabled || field.type === 'file' || field.type === 'reset' || field.type === 'submit' || field.type === 'button') continue;

        // Convert field data to a query string
        if ((field.type !== 'checkbox' && field.type !== 'radio') || field.checked) {
            serialized += '&' + encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value);
        }
    }

    return serialized;

};

Nun, da wir unsere serialisierten Formulardaten haben, können wir sie zu unserer URL hinzufügen.

// Submit the form
var submitMailChimpForm = function (form) {

    // Get the Submit URL
    var url = form.getAttribute('action');
    url = url.replace('/post?u=', '/post-json?u=');
    url += serialize(form);

};

Einen Callback hinzufügen

Ein wichtiger Teil der Funktionsweise von JSONP ist der Callback.

Herkömmliche Ajax-Anfragen geben Ihnen Daten zurück. JSONP übergibt stattdessen Daten an eine Callback-Funktion. Diese Funktion muss *global* sein (d.h. an das `window` angehängt und nicht innerhalb einer anderen Funktion).

Lasst uns eine Callback-Funktion erstellen und die zurückgegebenen Daten in der Konsole protokollieren, damit wir sehen können, was MailChimp zurückgibt.

// Display the form status
var displayMailChimpStatus = function (data) {
    console.log(data);
};

Nun können wir diesen Callback zu unserer URL hinzufügen. Die meisten JSONP verwenden `callback` als Query-String-Schlüssel dafür, aber MailChimp verwendet `c`.

// Submit the form
var submitMailChimpForm = function (form) {

    // Get the Submit URL
    var url = form.getAttribute('action');
    url = url.replace('/post?u=', '/post-json?u=');
    url += serialize(form) + '&c=displayMailChimpStatus';

};

Unser Skript in das DOM injizieren

Nun sind wir bereit, unser Skript in das DOM zu injizieren. Zuerst erstellen wir ein neues Skriptelement und weisen unsere URL als dessen `src` zu.

// Submit the form
var submitMailChimpForm = function (form) {

    // Get the Submit URL
    var url = form.getAttribute('action');
    url = url.replace('/post?u=', '/post-json?u=');
    url += serialize(form) + '&c=displayMailChimpStatus';

    // Create script with url and callback (if specified)
    var script = window.document.createElement( 'script' );
    script.src = url;

};

Als Nächstes holen wir das erste `

Nach oben