It's probably already there, but make sure this line is in your standard_layout.rhtml:
<%= javascript_include_tag :defaults %>
Add this function def to application_helper.rb:
def update_select_box( target_dom_id, collection, options={} )
# Set the default options
options[:text] ||= 'name'
options[:value] ||= 'id'
options[:include_blank] ||= true
options[:clear] ||= []
pre = options[:include_blank] ? [['','']] : []
out = "update_select_options( $('" << onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_5">dom_id.to_s << "'),"
out << "#{(pre + collection.collect{ |c| [c.send(options[:text]), c.send(options[:value])]}).to_json}" << ","
out << "#{options[:clear].to_json} )"
end
This calls update_select_options which needs to go into application.js:
function update_select_options( target, opts_array, clear_select_list ) {
if( $(target).type.match("select" ) ){ // Confirm the target is a select box
// Remove existing options from the target and the clear_select_list
clear_select_list[clear_select_list.length] = target // Include the target in the clear list
for( k=0;k <>
obj = $(clear_select_list[k]);
if( obj.type.match("select") ){
len = obj.childNodes.length;
for( var i=0;i <>
}
}
// Populate the new options
for(i=0;i <>
o = document.createElement( "option" );
o.appendChild( document.createTextNode( opts_array[i][0] ) );
o.setAttribute( "value", opts_array[i][1] );
obj.appendChild(o);
}
}
}
Add something like this to the form.rhtml (changing the name of the observable field as appropriate):
<%= observe_field 'item[facility_id]', :frequency => 0.5,
:update => 'location_id', :url =>
{ :controller => 'item', :action=> 'refreshLocation' },
:with => "'facility_id=' + escape(value)" %>
Add something like this to the controller:
def refreshLocation
@facilities = Facility.find(:all)
@facility = Facility.find(params[:facility_id])
@locations = Location.find_all_by_facility_id(params[:facility_id])
render :update do |page|
page << text =""> :description} )
end
end
This tidbit in the form.rhtml is the ultimate target of all this work (this is the drop down we want to refresh)
<%= select_tag "item[location_id]", options_from_collection_for_select(@locations,:id,:description) %>
If I missed any code attributions from the various sources we pieced this together from, I'm sorry. Write me and I'll make good and give attribution where appropriate.
If you have any questions about this, post 'em and I'll take my best shot at answering.
And finally, thanks Sheri! Couldn't have done it without you!
2 comments:
I got a set of cascading select boxes working after going through your example (thanks!), but wondered if you could explain what all the "clear" option stuff is about? That part I don't really get, and I still need to mess around with it more to fully understand what's going on.
So, I'm an 8 year perl coder, 10 year sysadmin, and after 2 years in management I have to write the first forum post of my career asking for help. :)
Seriously, though, it's amazing how such a common task has almost no "right way" to do it in such a thriving, active community.
Anyways, on to my problem, of which I am 100% sure is my doing.
What's this?:
render :update do |page|
page << text =""> :description} )
end
I (think) I understand that it allows you to dump some rubyish javascript into the page, but does that actually run without throwing an error? I just get:
syntax error, unexpected '}', expecting kEND
Also I get that it updates the div tag with the id location_id, right?:
:update => 'location_id'
But does that mean I should just wrap the select box in a div tag with location_id as the id? I tried that and my select box is replaced with:
try { text =""> :description} ) } catch (e) { alert('RJS error:\n\n' + e.toString()); alert('text =\"\"> :description} )'); throw e }
And that's only if I try to quote the "render :update" I mentioned above like so:
render :update do |page|
page << text =""> :description} )
end
Thanks so much in advance!
Post a Comment