Dirk Bergmann

Developer, panographer. Does consultancy work from own company. Lives in Chiang Mai, Thailand.

Twitter

Chiang Mai

Hua Hin

Thailand Hotels

ListVote - List. Vote. Learn.

Partnerseek - Find Partners

Multi-Level Nested Object Forms in Rails (with jQuery)

Complex forms were the focus of Railscasts 73, 74 and 75 and the latter episode outlined the rather involved way to get a single nested model to work correctly with form elements generated on the client via javascript.

Nested model forms built into Rails became the most requested feature and release 2.3 finally delivered with the** accepts_nested_attributes_for function**. Still, challenges remained, especially when trying to generate form elements on the client.

A suggested solution was an altered form builder pre-populated with the nested models, which was published in the complex forms sample application. This solution was ported to support jQuery, but an extension to multi-level nesting (> 2 levels) was still lacking.

Now a fork of the complex forms examples show off a solution with any level of nesting that is extremely easy to implement.

As ryanb states in his answer to this question on stackoverflow, proceed like so:

git clone git://github.com/ryanb/complex-form-examples.git
cd complex-form-examples
git checkout -b deep origin/deep
rake db:migrate
script/server

What about jQuery? Very easy. Simply replace the two functions in application.js with

function insert_fields(link, method, content) {
    var new_id = new Date().getTime();
    var regexp = new RegExp("new_" + method, "g")
    $(link).before(content.replace(regexp, new_id));
}

function remove_fields(link) {
    var hidden_field = $(link).prev("input[type=hidden]");
    if (hidden_field) {
        hidden_field.val('1');
    }
    $(link).closest(".fields").hide();
    } 

Complex forms with multiple levels of nesting is finally upon us. And super easy to implement.

**Update: **As jQuery won?t be able to see the newly added elements (because binding took place at $(document).ready()), check out jQuery live and the livequery plugin. The latter supports more events, including the onchange of a select and also works with jQuery < 1.3.

#

Blair: Got some help from Dan G. Switzer, II at: http://blog.pengoworks.com/ The JQuery calculation plugin is his. Here's what we came up with: $(function() { var selector = "input:visible[name^=opportunity[line_items_attributes]][name$=[value]]"; var total = $(selector).sum(); $("#totalSum").val(total); $(selector).live("keyup", function(){ var total = $(selector).sum(); $("#totalSum").val(total); }); $("a:contains('remove')").live("click", function(){ var total = $(selector).sum(); $("#totalSum").val(total); }); });

Blair: Interesting that you mention .live in your update. I've got the nested form working with jQuery - really surprised at easily it came together, thanks for sharing. Now I'm trying to show a running total of the values entered in the nested fields. The jQuery calculation plugin works fine, but it only matches elements that existed when the page loaded. Any thoughts on how to use .live or livequery to calculate a total that includes the newly added form elements?

Melvin Bruno: Love the blog. I've been creating auctions for small businesses for months now and carrying out pretty well... Greatful I found this place.