Wednesday 22 May 2013

Automatic Backbone model validation

Today I'm going to dig into Backbone.js validations and how to automate them. Backbone itself doesn't provide any proper validation. Fortunately, there is quite good plugin: Backbone.validation. It provides an easy way to define own constraints and error messages for models.

However, Backbone.validation plugin has one disadvantage. It doesn't provide any good way to transfer validation messages across multiple Backbone views nor provide events for single attribute validations. In simple applications this is not a problem, but huge user interface must be divided into multiple views and validation must work automatically for all of those, without generating too much processing overhead.

The solution?

First step was to implement per-attribute. Actually, Backbone.validation provides per-attribute validation callbacks but those are always bound to a view. In order to make our validations more modular, per-attribute validation events must be view-independent. We can create our own events "valid:<attr>" and "invalid:<attr>" by overriding the Backbone.Validation.mixin.validate function:


Ok. Now we have view independent validation events for attributes. Next step is to bind those events into views so that each input listens valid and invalid events from associated models. The problem is that there is no pre-defined information about available events because they are generated dynamically from model constraints. Thus, I've looped every input element from the view after render and used their name attribute for event binding:

In the above code, I've added also an automatic input-to-model binding so that every time when user changes the input, the changed value will be stored into associated model attribute. Validation binding and input-to-model bindings can be disabled from individual inputs by defining HTML5 data-attributes ignore-model="true" and ignore-validation="true".

Because these kind of validation and input-to-model bindings are kind of boilerplate code, I wanted to automate them by using CoffeeScript inheritance and Backbone.marionette plugin: all that developers must do is to inherit their new view classes from ItemView class and after that all validations and input-to-model synchronizations are working automagically! Cool, I think!

And usage...

Here is a little example code about the usage of our brand new "framework":

Of course our framework requires that our markup follows some specific conventions. I'm using Twitter Bootstrap so the framework expects that every validated input is inside control-group div. However, it shouldn't be non-trivial to tweak setValid and setInvalid methods form part 2 in order to make your own markup implementation. ;)

A working example can be found from jsFiddle: http://jsfiddle.net/RfcMK/4/

No comments:

Post a Comment