act_as_newbie

Keeping a newbie mindset, at all times.

Client_side_validations and Dynamic Nested Forms

| Comments

Last week I found a little caveat when using the client_side_validations gem with ajax-loaded forms. It didn’t work out of the box.

Digging through the sourcecode I found this comment

rails.validations.js
1
2
3
4
  // Main hook
  // If new forms are dynamically introduced into the DOM the .validate() method
  // must be invoked on that form
  $(function () { $('form[data-validate]').validate(); });

Ok, so I called $("#my-form").validate() on ajax:success and everything was fine! Except it wasn’t =/

The behavior I understood, after banging my head against the wall several times was: if the form was entirely rendered in my ajax call it would validate ok, but if I added some fields inside it dynamically then I’d start getting those nasty validators is not defined errors and everything would go boom!

So how do I add some fields to the form and keep them “validatable”? this issue gave me some insight. And after rummaging the code a little more I found that this gem registers the validators in the window object. This process is done inside the form renderer, and that’s why the full rendered forms worked and adding just some of the fields did not. To accomplish that I created this helper

1
2
3
4
5
6
7
8
9
  def add_dynamic_validators(builders)
    result = ""
    builders.each do |builder|
      builder.object.client_side_validation_hash.each do |validator|
        result += "window[form_id].validators['#{builder.object_name}[#{validator[0]}]'] = #{validator[1].to_json};\n"
      end
    end
    result.html_safe
  end

It recieves an array of form builders and inspect it for the validators added by the gem. Then it prints the resulting instruction within the form partial, inside a function, to which I pass the id of the form that I want to validate.

1
2
3
4
  function update_dynamic_fields(form_id)
  {
    <%= add_dynamic_validators builders %>
  }

Then after the fields (with the script block) were added the to form you can call

1
2
  var $form = $("#my-form");
  update_dynamic_fields($form.attr("id"));

I know this is hacky as hell, but with this I was able to keep using this gem even inside pages with lots of moving parts.

ICanHaz Templates - Dealing With the Lack of Dot Notation

| Comments

[UPDATE: 30/10/2011] According to this issue we now have dot notation in moustache.js! Yay!

The ICanHaz javascript templating system is just awesome. It is really simple, and powerful, BUT as all good things in life it’s not perfect! ICanHaz is built on top of moustache.js that, on his part, is a javascript implementation of the moustache templates. Originally the moustache implementation didn’t support dot notation for accessing nested objects. Like for instance

1
2
3
4
5
6
7
8
    var post = {
      title : "Post title",
      body : "post body",
      author : {
        name : "Rafael Barbosa",
        age : 26
      }
    };

Normally you can access the author’s name in my js files via dot notation like post.author.name, but until this commit this wasn’t possible within moustache’s templates and it still isn’t supported by the javascript implementation. So how can I access nested objects? The same way you iterate over arrays!

For the post object above, inside an ICanHaz template

And that’ll do it. There’s an open issue on the moustache.js github for the inclusion of the dot notation.

Show Hierarchical Data Using Recursive Partials

| Comments

Yesterday I needed to show a deep nested tree in a view. The first solution that crossed my mind was something along the lines of a recursive helper like this one.

1
2
3
4
5
6
7
8
9
10
11
12
def display_tree_recursive(tree, parent_id)
  ret = "<ul>"
  tree.each do |node|
    if node.parent_id == parent_id
      ret += "<li>"
      ret += link_to node.title
      ret += display_tree_recursive(tree, node.id)
      ret += "</li>"
    end
  end
  ret += "</ul>"
end

That’s ok for simple ul-li pairs but I needed much more markup since my task was to show this information as nested accordions. Wouldn’t it be better if I could define a partial and call it from inside itself passing the children as its locals variables? Guess what? It works just like that! =)

In the index view

1
2
3
4
5
6
7
8
9
10
11
12
<ul class="accordion">
    <% @sections.each do |section| %>
      <li>
        <h3><%= section.name %></h3>
        <div class="accordion-content">
          <ul class="accordion">
            <%= render "section/section_children", :section => section %>
          </ul>
        </div>
      </li>
    <% end %>
  </ul>

That section/section_children partial is the trick. Inside it we have

1
2
3
4
5
6
7
8
9
10
<% section.children.each do |child| %>
  <li>
    <h3 ><a href="#" class="header"><%= child.name %></a></h3>
      <div class="accordion-content">
        <ul class="accordion">
          <%= render "section/section_children", :section => child %>
        </ul>
      </div>
  </li>
<% end %>

and that’s it!

Starting Things Up

| Comments

Time to start sharing whatever knowledge comes my way! This will be the first post on this blog and I hope many will follow. I’ll mainly talk about Rails and its fellas, so if that’s your thing stick around!