mardi 18 novembre 2014

Knockout + Bootstrap + jQuery : simple forms validation

Introduction

Here is a simple implementation of dynamically toggle .has-error bootstrap css class, when input (or .form-control) value changes.

Knockout + Bootstrap + jQuery

Using these 3 JavaScript libraries make things easier. We will bind change event with Knockout, find the right DOM element with jQuery and finally apply to (or remove from) it the .has-error css class.

The code

HTML code :
<input type="email" class="form-control" placeholder="Enter your email" required data-bind="event: { change: validate }" />
or
<fieldset class="form-group">
    <label class="control-label" for="Email">Email address</label>
    <input id="Email" class="form-control" type="email" placeholder="Enter your email" required data-bind="event: { change: validate, invalid: validate }" />
</fieldset>


JavaScript code :

ko.applyBindings({
  validate: function(viewModel, event) {
    var element = event.target || event.srcElement;
    $(element).parent().toggleClass("has-error", !element.validity.valid);
  }
});

Displaying error comment

Append a span.help-block after the .form-control element :
<fieldset class="form-group">
    <label class="control-label" for="Email">Email address</label>
    <input id="Email" class="form-control" type="email" placeholder="Enter your email" required data-bind="event: { change: validate }" />
    <span class="help-block"></span>
</fieldset>

We need an error message object that looks like this :
var validation = {
  errors: {
    default: "Invalid value",
    valueMissing: "Required field"
  }
}

The binding model becomes :
ko.applyBindings({
  validate: function(viewModel, event) {
    var element = event.target || event.srcElement;
    for (var k in element.validity) {
      if (k != "valid" && element.validity[k]) {
        message = validation.errors[k] || validation.errors["default"];
      }
    }
    $(element).parent().toggleClass("has-error", !element.validity.valid)
      .children(".help-block").text(message);
  }
});

Updates [2014-11-19]

To apply this behaviour when the form is submitted, bind also the invalid event to the .form-control element.