Form-Validierung für Bootstrap

Es gibt verdammt viele Möglichkeiten, um Benutzereingaben zu validieren. Im Webumfeld werden es sogar mehr statt weniger. Hinzu kommen Anforderungen an das Design. Client oder Server? Ganz schön viel für einen kleinen Blogartikel, der sich um ASP.NET-Formulare in Verbindung mit Bootstrap 3 kümmert.

Bootstrap ist ein Framework für einfacheres Webdesign. Responsive Design fast ohne CSS anzufassen. Microsoft setzt in Visual Studio 2013 und seinem One ASP.NET Template auf die aktuelle Version Bootstrap 3. Ist also schon drin. Ideal also für eine schnelle Validierung am Client.

Das HTML Template setzt sich aus geschachtelten DIV zusammen und vor allem dem Attribut has-error. In der  Version 2 lautete das noch control-group und error.

   1:   <div class="form-group has-error">
   2:          <label class="control-label" for="text1">Feldbeschreibung
</label>
   3:          <div class="controls">
   4:              <input type="text" class="form-control" id="text1">
   5:              <span class="help-block">Fehlermeldung</span>
   6:          </div>
   7:  </div>

und sieht dann so aus. Der Fehler ist sozusagen hart verdrahtet.

image

Nun stellt sich sowohl für den ASP.NET MVC und auch den Webforms Frontend Designer die Frage, wie man die Validation Controls bzw. HTML Validation Helper dazu bewegt da mitzuspielen. Das Problem liegt vor allem darin, dass die Fehlermeldung einen übergeordneten Node im HTML Dom verändern muss. Aus Programmierersicht ist es ohnehin verpönt, Elemente (oder Objekte) in Abhängigkeit zu stellen.

Die Alternative, komplett neue Steuerelemente zu entwickeln, erscheint wenig verlockend.

Betrachten wir die Eingabevalidierung mit ASP.NET Web Forms unter Anwendung der vorigen Bootstrap HTML Vorlage. Es soll geprüft werden, ob die Eingabe eine gültige E-Mail-Adresse ist. Visual Studio schlägt in den Control-Eigenschaften die passende Regular Expression vor.

   1:  <div class="form-group" id="test1">
   2:          <asp:Label ID="Label2" runat="server" Text="Beschriftung"
   3:           CssClass="col-sm-2 control-label" />
   4:          <div class="controls">
   5:              <asp:TextBox ID="TextBox1" runat="server" 
CssClass="form-control">
   6:  </asp:TextBox>
   7:              <asp:RegularExpressionValidator 
ID="RegularExpressionValidator1" runat="server"
   8:                  SetFocusOnError="true"
   9:                  ErrorMessage="RegularExpressionValidator" 
ControlToValidate="TextBox1"
  10:  ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">
  11:  </asp:RegularExpressionValidator>
  12:          </div>
  13: </div>    

Als nächstes kommt JavaScript und JQuery Magic zum Einsatz. Mein großes Problem war herauszufinden, wo man während der Validierung einhaken kann. Das Validator Control blendet dynamisch ohne Postback die Fehlermeldung ein bzw. aus - dank moderner unobtrusive Validation von ASP.NET Webforms auch mit JQuery Validierung. Im HTML Code wird ein SPAN Element erzeugt. Data-Attribute werden für die Validierung verwendet.

   1:   <input name="ctl00$Inhalt$TextBox1" type="text" 
id="Inhalt_TextBox1"
   2:  class="form-control" />
   3:   
   4:  <span data-val-controltovalidate="Inhalt_TextBox1" 
data-val-focusOnError="t"
   5:  data-val-errormessage="RegularExpressionValidator" 
   6:  id="Inhalt_RegularExpressionValidator1" data-val="true" 
   7:  data-val-evaluationfunction="RegularExpressionValidator
EvaluateIsValid"
   8:  data-val-validationexpression="\w+([-+.&#39;]\w+)*@\w+
([-.]\w+)*\.\w+([-.]\w+)*"
style="visibility:hidden;">
RegularExpressionValidator</span>
   9:          </div>

Bleibt die Frage, wie man aus dem SPAN da, oder nicht da, auf ein übergeordnetes DIV kommt. Ginge, aber ich habe ein Event gefunden, das schon seit Ewigkeiten in der Library existiert, ValidatorValidate.

Diese Methode wird dann überschrieben, wie man das aus OOP so kennt, um seine eigene Logik (onAfter) hinten dran einzufügen. Dann wird die CSS Klasse has-error zugewiesen, wenn ein Fehler auftritt.

   1:  <script>
   2:   var proxied = window.ValidatorValidate;
   3:         window.ValidatorValidate = function () {
   4:          var result = proxied.apply(this, arguments);
   5:          onAfter(arguments);
   6:         };
   8:         var control = document.getElementById(arguments[0].
controltovalidate);
   9:         var validators = control.Validators;
   7:         var onAfter = function (arguments) {
  10:         var isValid = true;
  11:         for (var i = 0; i < validators.length; i++) {
  12:                  if (!validators[i].isvalid) {
  13:                      isValid = false;
  14:                      break;
  15:                  }
  16:              }
  17:             if (isValid) {
  18:                  $(control).closest('.form-group').
removeClass('has-error');
  19:              } else {
  20:                  $(control).closest('.form-group').
addClass('has-error');
  21:              }
  22:          };
  23:  </script>

 

Um ehrlich zu sein, bin ich mir nicht sicher, was ich mir im Detail damit einhandle. Falls es unter den Lesern welche gibt die dazu Feedback haben, per mail an hannesp at ppedv.de oder Facebook.com/preishuber.

Jedenfalls ist der Aufwand nun überschaubar. Einfach als JS-Datei ausgelagert und am besten in der Masterpage included.

Kommentare sind geschlossen