Josh Ford
Josh Ford

Reputation: 47

Following Or Unfollowing a User using Ajax causes href for other links to change? Images / Examples attached

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. Href is fine here.

When I unfollow the user in the middle, everything is still fine. 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? enter image description here

This has been doing my head in for the past few days... ANY help is REALLY appreciated. Thank you!

Upvotes: 0

Views: 49

Answers (1)

Toby 1 Kenobi
Toby 1 Kenobi

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

Related Questions