interacting select_tags using onchange

my view:

  <td>
    <div id="event_category_select">
      <%= render :partial => "event_category_select" %>
    </div>
    <br/>
    <div id="event_category_text_field">
      <%= render :partial => "event_category_text_field" %>
    </div>
  </td>
  <td>
    <div id="event_description_select">
      <%= render :partial => "event_description_select" %>
    </div>
    <br/>
    <div id="event_description_text_field">
      <%= render :partial => "event_description_text_field" %>
    </div>
  </td>

_event_category_select.html.erb:
<%= select_tag :select_category, options_for_select(@categories,
selected = @selected_category),
      {:onchange => remote_function(:url => {:action
=> :select_category}, :with => "select_category")} %>

_event_category_text_field.html.erb:
<%= text_field_tag :category, @selected_category, :size => 30 %>

_event_description_select.html.erb:
<%= select_tag :select_description, options_for_select(@descriptions,
selected = @selected_description),
      {:onchange => remote_function(:url => {:action
=> :select_description}, :with => "select_description")} %>

_event_description_text_field.html.erb:
<%= text_field_tag :description, @selected_description, :size => 60 %>

controller:

  def select_category
    @selected_category = params[:value]
    search_hash = {:select => "DISTINCT description"}
    search_hash[:conditions] = ["category = ?", @selected_category] if
@selected_category != ""
    @descriptions = ["", *Event.find(:all,
search_hash).map(&:description)]
    @selected_description = ""
    render :update do |page|
      page.replace_html "event_category_text_field", :partial =>
"event_category_text_field"
      page.replace_html "event_description_select", :partial =>
"event_description_select"
    end
  end

  def select_description
    @selected_description = params[:value]
    @categories = ["", *Event.find(:all, :select => "DISTINCT
category").map(&:category)]
    if @selected_description != ""
      selected_event = Event.find(:first, :conditions => ["description
= ?", @selected_description])
      @selected_category = selected_event.category if selected_event
    else
      @selected_category = ""
    end
    render :update do |page|
      page.replace_html "event_category_select", :partial =>
"event_category_select"
      page.replace_html "event_description_text_field", :partial =>
"event_description_text_field"
    end
  end

With ie 7.0 everything's fine, but with firefox 3.0:

When I select a category, the two ids are replaced. After that, I want
to select a description, but it doesn't send a request. However,
selecting another category does. The same the other way round, i.e.
when I begin with selecting a description.

The source code is of no avail, because with both browsers it never
changes whatever I select.

Any idea?

Thanks
Luma

Hey, do you solved your problem or found a work-around?

If so I'm interested in it because I do have a similar problem.

Thanks.
Flo.

sorry, I still didn't find a solution. I don't have much experience
with javascript.
Luma

From what I can see, the most likely cause of this is that there is an
issue with the dom, such that when you do the update, the browser is
not seeing the fields or ids correctly

A couple of suggstions:

Use firebug to carefully inspect the dom before and after the updates
and make sure the ids are ok and that the elements are structured
correctly.

If you cannot see anything obvious, strip the view code down so that
the only things being rendered are the actual select fields. Then you
should be able to see why the onchange is not firing.

If you get it down to very simple/minimal example that still
demonstrates a problem, post it here and i will see if i can repeat
it.

Tonypm

ps.

Looking again at the code, I suspect the problem may be that you are
updating table cells. I think i have seen something similar with ff.
In general, I tend to always update a whole row.

Tonypm

Very nice tool, I didn't know firebug.

I think I've found the reason of the problem: When you update fields
of a form, they forget to which form_tag they belong. (Why do we need
a form_tag for these select_tags, as they are only used for setting
other fields by onchange?)

Updating another partial containing the form_tag doesn't work, so
you've got to update the whole form. But I didn't find a way to update
a table row: A <div> can't be between a <table> and a <tr> element,
and a form_tag can't be between <tr> and <td>. A simple example:

<table cellpadding=10>
  <div id='test'>
    <%= render :partial => 'test' %>
  </div>
</table>

_test.html.erb:

<% form_tag do %>
  <tr>
    <td>
      number: <%= select_tag :select_number,
options_for_select(['','1','2'], selected = @number),
        {:onchange => remote_function(:url => {:action
=> :select_number}, :with => "select_number")} %>
    </td>
    <td>
      letter: <%= select_tag :select_letter,
options_for_select(['','a','b'], selected = @letter),
        {:onchange => remote_function(:url => {:action
=> :select_letter}, :with => "select_letter")} %>
    </td>
    <td>
      additional: <%= text_field_tag :additional, @additional %>
    </td>
  </tr>
<% end %>

  def select_number
    @number = params[:value]
    index = ['','1','2'].index(@number) || 0
    @letter = ['','a','b'][index]
    render :update do |page|
      page.replace_html "test", :partial => "test"
    end
  end

  def select_letter
    @letter = params[:value]
    index = ['','a','b'].index(@letter) || 0
    @number = ['','1','2'][index]
    render :update do |page|
      page.replace_html "test", :partial => "test"
    end
  end

I also included a field 'additional' which will also be updated with
the whole form. How can I keep the values of such fields?

Thanks,
Luma

1. You don't need the form tag if you are only updating by ajax.
Html purists might argue the point!

2. You can use any element to update from a partial. For example,
give the tr an id as in:
<tr id='update_me'>
then in the controller,
page.replace_html :update_me etc.....

3. Sometime I find it easier to include the <tr> tag in the partial
itself, so that the whole row, not just the inner html gets replaced.
In this case use page.replace :update_me in the controller.

4. You may find if you get rid of the form tags, that updating
individual <td>s may work, but I would be wary of it.

hth Tonypm

Without the form_tag, everything's fine with IE 7.0. But with firefox
3.0.3, I don't even get a request. (javascript completely enabled)

<table cellpadding=10>
  <tr id='test'>
    <%= render :partial => 'test' %>
  </tr>
</table>

_test.html.erb:

    <td>
      <%= select_tag :select_number, options_for_select(['','1','2'],
selected = params[:value]),
        {:onchange => remote_function(:url => {:action
=> :select_number}, :with => "select_number")} %>
    </td>
    <td>
      selected: <%= params[:value] %>
    </td>

  def select_number
    render :update do |page|
      page.replace_html "test", :partial => "test"
    end
  end

And using page.replace with <tr id='test'> in the partial leads to
something like http://railsforum.com/viewtopic.php?id=21678

Luma

You're right, the problem was just :with => "select_number"

Using :with => "'value='+value" works.

Thanks!