Judge: Simple JavaScript form validation for Rails
Since version 1.0 has just been released and I’ve settled on what I hope is a friendly interface, I thought it was probably time I wrote a bit about Judge, my client side form validation gem for Rails 3.
Context
There are some other gems out there that attempt to solve this problem, so it would be remiss of me not to mention them. Client Side Validations is feature-rich and does a lot of work for you. There’s also LiveValidation, which has been around for a long time and might be a good choice for people with legacy Rails apps that need Prototype.
I wanted a solution that was as small as possible. This is a simple job – no need for middleware, no need for extensions to core Ruby classes. I also wanted it to be as flexible as possible – no assumptions should be made about form markup, styles, classes and so on. I started hacking away, using the jQuery plugin pattern as a starting point for the client side code. It soon became clear that jQuery had to go. Writing Judge as a jQuery plugin was a mistake – the code I wrote ended up tightly coupled to specific event bindings, specific DOM elements etc. That kind of stuff should really be left for the user to decide.
Examples
Setup
Add validation to an attribute in your model.
class Thing < ActiveRecord::Base
validates :name, :presence => true
end
Use the Judge::FormBuilder
in your view. Add :validate => true
to the options hash of any form element that you wish to validate on the client side.
<%= form_for(@thing, :builder => Judge::FormBuilder) do |f| %>
<%= f.text_field :name, :validate => true %>
<% end %>
Quick validation
The judge
object has a static validate
method for immediate validation:
judge.validate(document.getElementById('thing_name'));
// => { valid: false, element: HTMLInputElement..., messages: { blank: "Can't be blank" } }
The same method used within a keyup
event handler (requires jQuery):
$('input#thing_name').keyup(function() {
var input = this;
console.log(judge.validate(input));
});
Note that we are not passing a jQuery object into the validate
method here, but the DOM element itself. The jQuery get method will often be of use when validating elements that have been wrapped by jQuery.
Validation with watchers
Most of the features of Judge are based around watchers – JavaScript objects that hold information about the form elements to which they point.
// instantiate watcher
var nameInput = document.getElementById('thing_name'),
nameWatcher = new judge.Watcher(nameInput);
// some time later:
nameWatcher.validate();
// => { valid: false, element: HTMLInputElement..., messages: { blank: "Can't be blank" } }
Validating stored elements
Most of the time, validating immediately on keyup
or change
will be enough to achieve the intended user experience. But there are times when storing a reference to a form element, or a group of form elements, can be useful. For example, validating elements conditionally based on user triggers. This is where the Judge store
comes in.
// store some text input elements
var textInputs = document.querySelectorAll('form.thing-form input[type=text]');
judge.store.save('foo', textInputs);
// retrieve watchers for your stored elements
judge.store.get('foo');
// => [ { element: HTMLInputElement... }, { element: HTMLInputElement... }, ... ]
// retrieve your stored elements
judge.store.getDOM('foo');
// => [ HTMLInputElement, HTMLInputElement, ... ]
// validate all elements stored against key 'foo'
judge.store.validate('foo');
// => [ { valid: true, ... }, { valid: false, ... }, ... ]
Use it
Go ahead! Feedback is all kinds of welcome.
gem "judge", "~> 1.0.0"