Reputation: 47
I'll try explain this strange situation as best as possible. Images / Examples are attached
I have a page dedicated to show all the users a particular user is following.
users_controller.rb
def following
@pals = current_user.following
end
following.html.erb
<% @pals.each do |pal| %>
<div class="following-user-btn">
<% if current_user_is_following(current_user.id, pal.wall.id) %>
<%= link_to 'Following' , unfollow_wall_path(pal.wall.id), remote: true, method: :post, class: 'unfollow-button' %>
<% else %>
<%= link_to 'Follow' , follow_wall_path(pal.wall.id), remote: true, method: :post, class: 'btn follow-button' %>
<% end %>
</div>
<% end %>
When I load the page, everything shows up fine, the Following button is next to each user accordingly and unfollowing a user works fine. However after clicking the unfollow button once it will change the href for the other users to the first user you unfollowed. You will not be able to Follow again if the following button is currently being used by another user.
Here is my relationships controller and my javascript
def follow_wall
if current_user.follow @wall.id
respond_to do |format|
format.html { redirect_to root_url }
format.js { render 'walls/follow_wall' }
end
end
end
def unfollow_wall
if current_user.unfollow @wall.id
respond_to do |format|
format.html { redirect_to root_url }
format.js { render 'walls/unfollow_wall' }
end
end
end
Unfollow_wall.js.erb
$('.unfollow-button').bind('ajax:success', function(){
$(this).closest('.unfollow-button').hide();
$(this).closest('.following-user-btn').html('<%= link_to 'Follow' , follow_wall_path(@wall.id), remote: true, method: :post, class: 'btn follow-button' %>');
});
Follow_wall.js.erb
$('.follow-button').bind('ajax:success', function(){
$(this).closest('.follow-button').hide();
$(this).closest('.following-user-btn').html('<%= link_to 'Following' , unfollow_wall_path(@wall.id), remote: true, method: :post, class: 'unfollow-button' %>');
});
I even tried changing it to this:
$('#follow-button').attr('class', 'btn unfollow-button')
.text('Following')
.attr('href', "/<%= @wall.id %>/unfollow_wall")
.attr('id', 'unfollow-button');
$('#unfollow-button').text('Follow')
.attr('class', 'btn follow-button')
.attr('href', "/<%= @wall.id %>/follow_wall")
.attr('id', 'follow-button');
No luck for either
Notice the href is correct for all users upon a fresh reload.
When I unfollow the user in the middle, everything is still fine.
Now when I Unfollow the top user the top user href changes to the middle user? This is where I'm really getting confused?
This has been doing my head in for the past few days... ANY help is REALLY appreciated. Thank you!
Upvotes: 0
Views: 49
Reputation: 5035
I don't think you should be binding an ajax:success
event at that point in the code.
Binding an event with a function to an element means that, from that time on, the element will watch for the event and react to it by running the function whenever the event happens. This means that the binding should be done before the expected time of the first event.
However Rails will run the JS in unfollow_wall.js.erb
as a response to the button being clicked - that's not a time for binding the function with an event, that's a time for running the function.
The way I would do this is to not do binding, but to use the wall id in the element identifiers on the page like this:
Here see the id of the outer div of each button
<%# following.html.erb %>
<% @pals.each do |pal| %>
<div id="following-user-btn-<%= pal.wall.id %>">
<% if current_user_is_following(current_user.id, pal.wall.id) %>
<%= link_to 'Following' , unfollow_wall_path(pal.wall.id), remote: true, method: :post, class: 'unfollow-button' %>
<% else %>
<%= link_to 'Follow' , follow_wall_path(pal.wall.id), remote: true, method: :post, class: 'btn follow-button' %>
<% end %>
</div>
<% end %>
and in the js just find the button with the right id in the outer div
# unfollow_wall.js.erb
$('#following-user-btn-<%= @wall.id %>').find('.unfollow-button').hide();
$('#following-user-btn-<%= @wall.id %>').html('<%= link_to 'Follow' , follow_wall_path(@wall.id), remote: true, method: :post, class: 'btn follow-button' %>');
the js code in the unfollow_wall.js.erb
file is just as it is here in entirety, not enclosed in a bind function.
The same would apply to the other js file of course.
Upvotes: 1