From: "spiegela@..." Date: 2005-05-14T01:10:29+09:00 Subject: non-ajax dynamic form in Rails I've been fighting to get a dynamic form working w/ rails for a few days, and finally got it working. My problem wound up being that all of my hidden select boxes had the same name and id, and so the first hidden box always passed its value. I thought I'd share my solution, and ask for suggestions for improvements also. My project is an online document repository, and (the relevant part) looks like this: Category --one-to-many--> Subcategory --one-to-many --> Document. There's no direct relationship between the categories and the Document, only through the Subcategory. But in the form, I wanted to limit the displayed subcateogories based on a dummy category select box. So the rhtml looks like:

Category
<% subcategory_selects = "" %> <% @categories.each do |category| %> <% subcategory_selects += "\n" << "\n\n" end %>

Subcategory
No Category Selected <%= subcategory_selects %>

I'm generating the select tags manually to avoid setting id and name when it first loads. Also, I'm setting the id of the span to a value I can pick up in "toggleSubcategory". My javascript function "toggleSubcategory" changes the display, the id, and the name: function toggleSubcategory(evt) { var selCat; evt = (evt) ? evt: (( windows.event) ? event : null ); if(evt) { var elem = (evt.target) ? evt.target : (( evt.srcElement ) ? evt.srcElement : null ); if(elem) { selCat = elem.value; } } if(typeof curCat == "undefined") { curCat = 0; } var curBlock = document.getElementById( curCat + "_subcategory" ); curBlock.style.display = 'none'; if( curCat != 0 ) { curSel = findChildByTag( curBlock, "SELECT" ); if( curSel ) { curSel.setAttribute( "name", "" ); curSel.setAttribute( "id", "" ); } } var selBlock = document.getElementById( selCat + "_subcategory" ); selBlock.style.display = 'block'; newSel = findChildByTag( selBlock, "SELECT" ); if( newSel ) { newSel.setAttribute( "name", "document[subcategory_id]" ); newSel.setAttribute( "id", "document_subcategory" ); } curCat = selCat; } function findChildByTag(node, tag) { var curNode = node.firstChild; // we'll stop walking the children if we hit the // first requested tag, or if we're out of children while( curNode.nodeName != tag && ! curNode.lastChild ) { curNode = curNode.nextSibling; } // did we get it? if( curNode.nodeName == tag ) { return( curNode ); } else { return( FALSE ); } }