1

Firstly, sorry for my English. I'm Brazilian guy that is improving yet.

I want create a helper tag called "collection_cascading_select". That helper is similar to "collection_select", but he has one more argument called "source". The "source" is the other collection in the view.

Ever that other option is select in the "source", a JavaScript function needs run to gets his value. Then populate the "collection_cascading_select" collection agreed of that value.

That gets confusing! I'm one week in this problem and my Brazilian brothers aren't help me.

Thanks!

[EDIT]

@Samo

I get it to work, but with some changes.

var success = function(response) {

for (var item in response){

    var id = response[item].breed.id   <--------------------  
    var name = response[item].breed.name <-------------------  
    var option = $(document.createElement('option')).val(id).html(name)
    dependentDropDown.append(option)  
  }  
}

I don't understand how FOR IN works.

user229044
  • 232,980
  • 40
  • 330
  • 338
Theo B
  • 351
  • 1
  • 3
  • 12

1 Answers1

0

It sounds like the answer you're looking for is a custom form builder. You could create your form builder and inherit from the Rails form builder, and then set that form builder as the default across your application. Then you could define an element called dependent_dropdown or cascading_selection, etc. This element would probably take the id of the source dropdown. Your helper would output a collection_select but it would also output some JavaScript that would fire an AJAX call when the source dropdown changes.

Of course, you don't have to do it this way. You could just use a collection_select, add some attributes to the source dropdown (i.e. :class => 'source_for_dependent', :dependent => some_id), and then hook up some JavaScript in your application.js that looks for collections with the source_for_dependent class, and when the onchange event fires it grabs the id from the dependent attribute and fires an AJAX call.

Either way, here's an example of your JavaScript (using jQuery)

$('select.source_for_dependent').change(function() {
  var id = // get the id of the dependent dropdown, perhaps by $(this).attr('dependent')
  var dependentDropDown = $('#' + id);
  dependentDropDown.empty();
  var success = function(response) {
    for (var item in response) {
      var option = $(document.createElement('option')).val(item.val).html(item.text);
      dependentDropDown.append(option);
    }
  }

  $.get('/some_controller/some_action/' + $(this).val(), success);
}

The success handler gets passed into jQuery's get method. It takes a JSON response as an argument. We loop through the response, and for each item, we create an option, pulling the value and the text off the item, and we append that to the dependent dropdown. Your controller might look something like this:

def some_action
  @obj = SomeClass.find(params[:id])
  respond_to do |format|
    format.js { render :json => @obj }
  end
end

Edit

Which controller you target is up to you. Let's say Dropdown A targets resource A, and Dropdown B targets resource B. An object of type A should have a list of objects of type B. If you're going after the show action for object A, then your as_json method for object A needs to include its B associations. This article shows examples of this.

Otherwise, you could target the index action for resource B. Making B a nested resource of A would be an easy way to key off the id of A to get all objects of type B which have a foreign key that points to A.

Samo
  • 8,202
  • 13
  • 58
  • 95
  • Of course, my mistake. You'd have to give the source dropdown a different class... I can't think of a good name, maybe 'source_for_dependent' or something like this. Say, if my answer was helpful, how about an up vote or a green tick? :) – Samo Dec 23 '10 at 21:46
  • In the FOR IN iteration, the ITEM return a string, not an object. Because this, I can´t manipulate the data. odd I get work without the iteration. Other thing... I needed to specify the data type (json) in the $.get to work. Thanks for your valious help. – Theo B Dec 28 '10 at 21:47
  • It is up to you to know what's contained in your response object. Setting a breakpoint in your handler function and inspecting it using firebug will show you how to access your object's properties. If you need associations, you might have to override the as_json method in your model to include them. Also, there is a way to specify that all XHR requests accept JSON so that you don't have to specify it for each AJAX call. See here: http://railscasts.com/episodes/136-jquery – Samo Dec 29 '10 at 19:13
  • I'm not getting updates from my (this) question in my email. odd – Theo B Jan 03 '11 at 18:40
  • "If you need associations, you might have to override the as_json method in your model to include them.". Sorry, I don´t understand this. – Theo B Jan 03 '11 at 19:18
  • @Theo B: Another option is to go after the association's controller. I've updated my answer to explain. – Samo Jan 03 '11 at 20:32
  • Everything are work. I thought that FOR IN (javascript) was like Ruby iteration, where the variable is the object. But in javascript, the variable is only a counter. Now, I'm doing the "collection_cascading_helper". I'm studying the difference between a form_helper and a form_builder. Is confusing a bit. More one time... thanks Samo – Theo B Jan 05 '11 at 22:56
  • @Theo B: `for in` in JavaScript should give you properties, not an index. Something is weird. I just did this in Firebug: `var obj = { foo: 'bar', bar: 'baz', baz: 'foo' }; for (var prop in obj) { console.log(prop) }` And the output was `foo bar baz` so I'm not sure why it's giving you an index. As for form_builders... those are a great way to override the way your existing helpers work and to define new ones all in one place. I strongly recommend using them if you find yourself defining a lot of custom form_helpers – Samo Jan 06 '11 at 15:33
  • @Theo B: It should only return an index if you are looping through an array. Here's a quote from that page: "Note: The variable argument can be a named variable, an array element, or a property of an object." Again, it all depends on the structure of your JSON object, and it's up to you to understand that structure. If you don't believe me, construct a JavaScript object and try it for yourself :) – Samo Jan 10 '11 at 20:18
  • @Samo: Is TRUE! Thanks for all explanation. Thanks so much. – Theo B Jan 29 '11 at 06:32