Tuesday, 28 May 2013

Rails Client Side Validations and jQuery Mobile

I started a mobile project using Rails 4 and jQuery Mobile 1.3. One of the things that I missed from my ASP MVC days were client-side validations generated off the server-side validations (i.e. they were for free with no extra effort on my part).

After Googling I found this gem client_side_validations, and found a screencast on RailsCasts here,
and was re-assured that this gem was what I needed. However getting it to work with Rails 4 and jQuery Mobile took a little effort, so I am going to quickly explain what I did to get up and running.

First of all I followed the standard instructions on the CSV GitHub page:


but it did now work with Rails 4, so I used Bundler to get the 4-0-beta branch.

gem 'client_side_validations', github: 'bcardarella/client_side_validations', branch: '4-0-beta'

Then I went to the initializer, uncommented the relevant parts to get things working:


I then added :validate => true to my haml form_for helpers, and  removed the old validation display code as it it not needed in CSV. Finally I added  //= require rails.validations to application.js.

Then I ran the mobile app, and experienced two problems. 1) The validation messages were displayed inside the textboxes, and 2) the validations did now work after a page change.

Before
To solve the validations appearing in the textbox I positioned them to absolute.

/* Setting the errors to absolute gets them out of the textbox and below as expected*/
.field_with_errors
{
  .message
  {
    position: absolute;
    display: list-item;
    line-height: 11px;
    font-size: 11px;
    list-style-type: none;
    color: red;
    font-weight: bold;
  }
}


After

I then had one final problem, and that was the CSV uses document.ready(), which does not fire when jQuery Mobile changes a page using AJAX (its default).

So I imported the assets, as referred to higher up in this post, and scrolled to the very bottom of rails.validations.js and changed this:

$(function() {
    ClientSideValidations.disableValidators();
    return $(ClientSideValidations.selectors.forms).validate();
  });

to this:

  $(document).bind('pageshow', function() {
    ClientSideValidations.disableValidators();
    return $(ClientSideValidations.selectors.forms).validate();
  });


and everything is now working!


2 comments:

  1. Lee, thanks for the good post. Was there a particular reason why you bound to 'pageshow' vs 'pageinit'? Thanks!

    ReplyDelete
  2. I kept having problems with the page load, and everyone on StackOverflow kept suggesting 'pageshow' so I switched to using that event and I never had anymore trouble. The jQuery Mobile docs suggest 'pageinit', but in practice it caused problems.

    ReplyDelete