Sebastian Becker: HTML5-Formularvalidierung Änderung der Fehlermeldungen mit Loop

Hallo,

ich möchte gerne die Fehlermeldungen für eine HTML5-Formularvalidierung ändern.

Der dafür entwickelte JavaScript-Code ist unten angegeben und kommentiert.

Das Problem ist, dass mit field.setCustomValidity(msg) nicht der Inhalt der jeweils in der Schleife gesetzten Variable msg mit der richtigen Fehlermeldung gesetzt wird, sondern bei allen Durchgängen der Wert aus dem letzten Arrayelement.

Ich weiß nicht, ob dies an meiner Schleife, oder an dem Skriptteil zum Überschreiben der Default-Fehlermeldungen liegt, und bin nun mit meinem Latein am Ende.

Wäre für Hinweise auf die Fehlerursache dankbar.

Grüße aus Berlin,

Sebastian Becker

--------------------------------------------------------------------

  
// Array mit den IDs der zu prüfenden Felder  
// (Die IDs der zu prüfenden Felder und die Indexe des Fehlermeldungsarrays sind identisch. Die IDs könnten natürlich auch direkt aus dem JSON-Array ausgelesen werden)  
var msg_id_array = ["subject","message","firstname","lastname","zip","location","street","email","phone"];  
  
// JSON-Array mit Fehlermeldungen aus externer Datei  
var mail_msg = {  
"subject":"Bitte wählen Sie ein Anliegen (Betreff) aus.",  
"message":"Bitte geben Sie Ihre Nachricht ein.",  
"title":"Bitte wählen Sie Ihre Anrede aus.",  
"firstname":"Bitte geben Sie Ihren Vornamen ein.",  
"lastname":"Bitte geben Sie Ihren Nachnamen ein.",  
"street":"Bitte geben Sie Ihre Straße und Hausnummer ein.",  
"zip":"Bitte geben Sie Ihre Postleitzahl ein.",  
"location":"Bitte geben Sie Ihren Wohnort ein.",  
"email":"Bitte geben Sie eine eMail-Adresse ein.",  
"email_valid":"Bitte geben Sie eine gültige eMail-Adresse ein.",  
"phone":"Bitte geben Sie eine gültige Telefonnummer ein."  
};  
  
// beim Klicken auf den Submit-Button  
$("#submit").on("click", function()  
{  
for(var i=0; i<msg_id_array.length; i++) { // loop through ID array  
msg_id = msg_id_array[i]; // get IDs  
msg = mail_msg[msg_id]; // get error message  
  
alert("#" + msg_id + ': ' + document.getElementById(msg_id).validity.valid); // nur zum Testen (hier stimmen die Variableninhalte)  
  
// Hier der Code der nicht funktioniert ...  
$("#"+msg_id).on('change invalid', function() {  
var field = $(this).get(0);  
field.setCustomValidity('');  
if(!field.validity.valid) field.setCustomValidity(msg);  
});  
  
  
} // end for loop  
}); // end function  

  1. Hallo,

    Das Problem ist, dass mit field.setCustomValidity(msg) nicht der Inhalt der jeweils in der Schleife gesetzten Variable msg mit der richtigen Fehlermeldung gesetzt wird, sondern bei allen Durchgängen der Wert aus dem letzten Arrayelement.

    Ja, richtig beobachtet. Das liegt daran, dass die erzeugte Handlerfunktion eine Closure ist und über msg auf die Variablen des äußeren Gültigkeitsbereichs zugreift. In dem Moment, in dem die Funktion ausgeführt wird, ist der äußere Code komplett durchgelaufen und damit hat msg den Wert der letzten Zuweisung.

    Das liegt daran, dass das gesamte Variablenobjekt des äußeren Scopes in der Scope-Chain liegt. Es werden also keine einzelnen Variablen mit ihrem aktuellen Wert eingeschlossen, sondern das ganze Variablenobjekt wird konserviert und bleibt verfügbar, wie es ist. Zur Erklärung der Interna siehe http://molily.de/javascript-core/.

    In deinem Code ist msg anscheinend eine globale Variable, was die Sache etwas ändert, aber das Grundprinzip ist dasselbe. Es sollte natürlich eine lokale Variable sein – nicht das »var« vergessen! Das würde aber nichts im Hinblick auf deine Frage ändern.

    Es gibt hier verschiedene Lösungsmöglichkeiten. Eine einfache ist, für jeden Schleifendurchlauf eine Funktion auszuführen, die die Message als Parameter/Variable hat und deren Wert sich nicht ändert.

    var setValidityMessage = function(id, msg) {  
      $('#' + id).on('change invalid', function() {  
        // Diese Funktion schließt die Variablen des setValidityMessage-Aufrufs ein,  
        // id und msg sind die richtigen und ändern sich nicht mehr  
        var field = $(this).get(0);  
        field.setCustomValidity('');  
        if (!field.validity.valid) {  
          field.setCustomValidity(msg);  
        }  
      });  
    };  
      
    $('#submit').on('click', function() {  
      for (var i = 0, l = fields.length; i < l; i++) {  
        var id =;  
        var msg =;  
        setValidityMessage(id, msg);  
      }  
    });
    

    Mathias

  2. Meine Herren!

    ich möchte gerne die Fehlermeldungen für eine HTML5-Formularvalidierung ändern.

    Der dafür entwickelte JavaScript-Code ist unten angegeben und kommentiert.

    Unter einer HTML5-Validierung verstehe ich eigentlich eine Formular-Validierung mit HTML5-Bordmitteln ohne JS, aber egal.

    Das Problem ist, dass die Variable 'msg' zum Zeitpunkt, wenn der Event-Handler aufgerufen hat, wirklich den Wert aus der letzten Schleifen-Iteration angenommen hat.

    Das könntest du zum Beispiel mit bind() lösen.

    Ungetestet:

      
    $("#"+msg_id).on('change invalid', (function(msg) {  
       var field = $(this).get(0);  
       field.setCustomValidity('');  
       if(!field.validity.valid) field.setCustomValidity(msg);  
    }).bind(null, msg));  
    
    

    Das Prinzip nennt sich Currying.

    --
    Hey Girl,
    i wish you were asynchronous, so you'd give me a callback.