Reputation: 1781
I have a Rails application that has a displayed table of organizational leaders with a pair of radio buttons for each to indicate if they are 'Active' or 'Retired.' When a button is pressed, Ajax is used to save the state to the database and a success message (or failure message) is displayed that then fades away as programmed. However, while the first button change on any leader seems to work, subsequent change events on each leader are not detected. I've found several posts with problems similar to this, but none of the solutions in those seem to work reliably. I must be missing something.
The top level view contains the line below that identifies the id
of the table cell for a particular leader and renders the cell from a partial.
<td id="status_<%= leader.id %>_cell"><%= render(:partial =>
"connections/edit/leader_status", :locals => {
:leader => leader, :display_response => "" } ) %>
</td>
The id
above is passed through data-update
as the element to be updated to jQuery. The partial _leader_status.html.erb
contains:
<%= display_response.html_safe -%>
<%= radio_button_tag("status_#{leader.id}", 'Active', (leader.role == 'ActiveLeader'),
:class => "leader_status", data: { url: url_for(action: :toggle_leader_status,
id: leader.supporter.id ), update: "status_#{leader.id}_cell"}
) %> Active
<%= radio_button_tag("status_#{leader.id}", 'Retired', (leader.role == 'RetiredLeader'),
:class => "leader_status", data: { url: url_for(action: :toggle_leader_status,
id: leader.supporter.id ), update: "status_#{leader.id}_cell"}
) %> Retired
The controller code in toggle_leader_status
that responds to re-render the status cell is:
render(:partial => "connections/edit/leader_status", :locals => {
:leader => @entity.leader,
:display_response =>
"<div id='#{id}' class='#{klass}'>#{message}</div>" +
"<script type='text/javascript'>$('##{id}').fadeOut(#{duration})</script>"
})
And the jQuery code is:
<%# parameterized so only one copy is needed for all radio buttons %>
<script>
$(function($) {
$(".leader_status").change(function(){
// get id of element to stuff response into
var update_id = "#" + this.getAttribute('data-update');
$.ajax(this.getAttribute('data-url'), {dataType: 'text'}).done(
function(data) { $(update_id).html(data); } // problem part
);
})
});
</script>
The first time I click a radio button that changes its state, the HTML of the page is updated correctly (verified through FireBug)--usually-- and display_response message is displayed and fades as expected. If I then click the alternate radio button nothing happens. However, on some occasions when I click a button everything seems to happen but the display of the button changes back to its prior state. If I replace the problem part:
$(update_id).html(data);
with
alert("An Event! " + data);
The alert happens every time. With the problem code, updating the table cell is blocking subsequent change events from happening. If I change:
$(".leader_status").change(function(){
to
$(".leader_status").live('change', function(){
this works better, but still only, say, 90% of the time. If I use .on
instead, it works maybe 10% of the time. Any suggestions?
Upvotes: 1
Views: 1143
Reputation: 9095
Bind the event to one of the element's parents that does not change.
Like this:
$('table').on('change', '.leader_status', function(){
});
Upvotes: 4