Validations with Ember.js

These days, with the rise of the single page applications, there has been a steady rise in the number of complete websites that are built on a client side JavaScript framework.
At any given point of time, these sites have always had the need for validations that they need to run client side.

Recently, while working on a pet-project using Ember.js as the client side framework and jQuery for running my client side validations, I came across a rather interesting question.
How would you handle client side validations with a framework such as Ember.js? 

The confusion…

The validations are run on the actual fields, which are the part of the view, but they are triggered and handled in an event handled by the controller. So where do the validations go?

Lets have a look at the HTML I have

</pre>
<form id="form">
<div><label for="txtFirstName">First Name</label>
 <input id="txtFirstName" type="text" placeholder="Enter First Name" /></div>
<div><label for="txtLastName">Last Name</label>
 <input id="txtLastName" type="text" placeholder="Enter First Name" /></div>
 <button>Submit</button></form>
<pre>

Now looking at the above code, we know that we have 2 fields that we need to validate, on clicking the Submit button.
The validation of the code will go in the View as we already know. And we also know that the event ‘submit’ will be handled by the Controller.

So, how do we invoke the View from the Controller? Lets have a look…

Ember.js has a concept of mixins that we can use. And for this kind of a case, we are going to use the Ember.Evented mixin. Lets see how

App.UserController = Ember.ObjectController.extend(Ember.Evented, {
   actions:{
      submit: function(){
         // This code will handle the submit event
      }
   }
});

Notice, how the Ember.Evented mixin has been added to the Object Controller…
Now let us have a look at the View.

App.UserView = Ember.View.extend({
   didInsertElement:function(){
      this.get('controller').on('submit', $.proxy(function(){
         //This code will be invoked when the controller triggers the submit event
      }, this));
   }
});

And now we will add the triggering logic to the controller.

App.UserController = Ember.ObjectController.extend(Ember.Evented, {
   actions:{
      submit: function(){
         this.trigger('validate');
      }
   }
});

Now with this, we have manged to invoke the View from the Controller.

The reason we used Ember.Evented in this case, is that the Ember.Evented mixin gives us the function ‘on’ that can be bound to the Controller. This function tells Ember that when the Controller triggers the ‘validate’ method, call the proxy function that is defined. The proxy function takes a parameter which will act as the context for the internal function.

Let us now add the validation code in the view.

App.UserView = Ember.View.extend({
   didInsertElement:function(){
      this.get('controller').on('validate', $.proxy(function(){
         this.validate();
      }, this));
   },
   validate: function(){
      var validator = $("#form").validate(validations.formValidations);
   }
});

We have defined a class validations, that has all the validations for the form in a field called ‘formValidations’. The validator that we have defined here can now be used to validate the fields.

But now, we come across another problem…How do I let the controller know if the fields are valid or not?

Well that is also pretty simple. Lets have a look at how we need to modify the View for enabling this behavior.

App.UserView = Ember.View.extend({
   didInsertElement:function(){
      this.get('controller').on('validate', $.proxy(function (validation) {
         validation.isValid = this.validate();
      }, this));
   },
   validate: function(){
      var validator = $("#form").validate(validations.formValidations);
      if(!validator.valid()){
         validator.focusInvalid();
         return false;
      }
      return true;
   }
});

So looking at the above, we notice that an argument has been passed to the proxy function called requestValidation. 
In the body of the function, we are assigning the isValid property of this object and in the validate function, we are returning the valid status based on the validations that we have defined.

Now let us look at how this requestValidation can be sent and received by the Controller.

App.UserController = Ember.ObjectController.extend(Ember.Evented, {
   actions:{
      submit: function(){
         var validation = {isValid: false};
         this.trigger('validate', validation);
         if(validation.isValid){
            //Validation passed. Do something here.
         }
      }
   }
});

Essentially, we have passed a new object with the isValid property set to default false to the trigger method and this will internally be set and reflected back when the View modifies it.

That was a brief example of how we can use the Ember.Evented mixin to do validations client side without writing a lot of spaghetti code and keeping things simple.

For those of you who are wondering how to go about validations with Twitter Bootstrap, you can check out my post here.

You can also find a gist of the entire code here.

Abhimanyu Chakravarty

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s