AJAX Form Validation for Rails
Last Saturday at the Chicago Ruby User Group I gave a short presentation on Rails and AJAX. For part of the presentation I decided to solve a problem that’s haunted me as a web developer for some time – form validation.
Here’s the dilemma:
Here’s the solution:
I started by searching for solutions for this. As it appears, I’m not the only developer in the room who wants AJAX validation. Here’s what I found:
I opted, for the sake of practice, to use these as inspiration to my own solution, which goes something like this:
I wanted my solution to be equally elegant as Rails’ non-Ajax solution, so I created a method
observe_field, wiring up the Ajax request to the field we’re monitoring. Then, using
content_tag produces an empty tag which will serve as our feedback placeholder. It returns all that HTML/JS to the browser. But, we haven’t done any validation yet. For that we need a validate action that can be called on whatever model you’re working with (in this case I’m working with a User):
Now, we’re cooking. As the user moves from field to field, the AJAX request we wrote is created, firing
validate. Validate then uses the
valid? method to populate the
errors collection on our model which in turn allows us to return the same error messages Rails would if we were using
Now we just implement it. Call our new
error_message_for method right after the input field like so and that’s a wrap. The HTML and JS is returned to the browser when the page renders the first time. When focus leaves a particular field, its value is sent down to the server for validation, and the server replies with whatever applicable error messages, which are displayed in the originally empty HTML generated to begin with.
You may have noticed some code in there referring to
:hint. I figure, while we’re in there let’s add support for a hint to be displayed before any validation occurs, and a success message to display when validation is passed.
The best part of the whole thing, is it’s really DRY (Don’t Repeat Yourself), and therefore simple. Change your validation rules, and the UI updates dynamically. In addition the same approach can be used on any form that has an underlying model associated with it.