Skip to content

Rails 3, HTML 5 and client-side forms validations using Validator

02/09/2010

There are many client-side JS forms validations librairies available on the Internet. There are also many Rails plugins and FormBuilders gems.
While working on a new project using Rails 3, I wanted to find an easy way to validate my forms client-side using JS. I also usually don’t use plugins like Formtastic, I prefer writing my own custom FormBuilder for each project in collaboration with the webdesigner…

I found Validator by the flowplayer team. This Javascript library is just great. Why? Because it uses some HTML 5 new attributes to define validations on the form inputs. And guess what? It works perfectly with the new Rails 3 HTML 5 helpers.
You can just map this library on all your <form> tags in your application.js, use some HTML 5 attributes and get instant and unobtrusive client-side validations.

In your view (form) :

  ...
  <%= f.email_field :email %>
  ...

In your application.js :

  $("form").validator();  // Validate all forms...

Add the validator library in your main layout, and « BOOM! » instant validation!

What if your text_field is mandatory? Just add :required => true in the options, like this :

  ...
  <%= f.text_field :street, :required => true %>
  ...

You can also do some Regexp validation using the « pattern » attribute, like this :

  ...
  <%= f.text_field :login, :required => true, :pattern => "[0-9a-zA-Z_\-]{6,}" %>
  ...

Alongside email_field, there are other HTML 5 helpers that are included by default in Rails 3 : number_field, range_field, search_field, telephone_field, url_field, see the ActionView::Helpers::FormHelper API for more information about these new helpers.

Of course you cannot do complex validations or validations that require a server-side callback (like uniqueness validations) only by using HTML 5 attributes. But IMHO, the few attributes used by Validator are really a good start if you want something light and don’t want to use some bloated library or plugin. Take a look at the Validator documentation to see all the attributes and advanced options you can use (i18n is also possible!).

And… One more thing ! I wrote a simple module that easily integrates with any custom FormBuilder. It does simple reflection on the current model instance to automaticaly set some HTML 5 attributes. Here it is…

Gist

module FormBuilderHelpers
  class Html5
    def self.options_from(object, attribute)
      return {} unless object.class.respond_to?(:validators_on)
      
      {}.tap do |options|
        options[:required] = true if object.class.validators_on(attribute).any? { |validator| validator.is_a?(ActiveModel::Validations::PresenceValidator) }
        
        if validator = object.class.validators_on(attribute).select { |validator| validator.is_a?(ActiveModel::Validations::InclusionValidator) && validator.options[:in].is_a?(Range) }.last
          options[:min] = validator.options[:in].min
          options[:max] = validator.options[:in].max
        end
      end
    end
  end
end

As you can see for now, it just returns a default options hash with the required and min/max attribute (if the model instance class has validates_presence_of or validates_inclusion_of with a Range).
At first, I also wanted to add the pattern attribute if a validates_format_of is used, but unfortunately the Ruby and JS regexps are often different… I did not find an easy way to reuse them directly (if you find a workaround, tell me :-)).

Then, in your FormBuilder, just use the module to get the default options hash :

  ...
  def text_field(attribute, options = {})
    options.reverse_merge!(FormBuilderHelpers::Html5.options_from(object, attribute))
    ...
  end
  ...
Publicités

From → rails, ruby

7 commentaires
  1. It’s too bad you have to duplicate all the validation information you put in the model into your views. Hard to keep things DRY when you are using this. I guess it’s better than writing all the js by hand though.

    BOb

    • Hi, have you read all the article :p ? At the end I give a small module to do basic reflection on your models and get automatic required => true if the attribute has validates_presence_of. Of course, this is not a lot, but that’s just the beginning…

  2. just what i was looking for.. thanks! 🙂

  3. You should also checkout my client_side_validations gem:

    http://github.com/dnclabs/client_side_validations

  4. Excelent tip! mainly for the code in the module FormBuilderHelpers. Thanks!

  5. For those interested the ClientSideValidations gem has been rewritten: https://github.com/bcardarella/client_side_validations

Trackbacks & Pingbacks

  1. simple client side validations using validator « ssssssssssscripting !!!

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :