3

I am trying to make a follow/unfollow button. The follow button works fine. On click I change the button id to "unfollow" but when I click the button again (when it has the id "unffollow") it acts as if it still has the id of "follow" which means it's still using the first ajax method as so:

$("#fbtn").on('click',function(){ 
    var fbtn = $('#fbtn');
    var followee_name = $('#author').text();

        $.ajax({
            url: '/follow',
            method: 'POST',
            //dataType: 'application/json',
            data:{followee_name:followee_name},
            success: function(response){ 
            console.log("Followed")
            fbtn.text('Unfollow');
            fbtn.attr('id','unfollow');
            }
        });
});

Then:

$("#unfollow").on('click',function(){ 
    var unfollowbtn = $('#unfollow');
        $.ajax({
            url: '/unfollow',
            method: 'DELETE',
            //dataType: 'application/json',
            success: function(response,err){ 
            if(err){
                console.log(err);
            }
            console.log("Unfollowd")
            unfollowbtn.text('Follow');
            unfollowbtn.attr('id','fbtn');
            }
        });
});

HTML:

<a id="author" href="#"><%= showPost.username %></a> //this displays a username
<button style="width:100px;" type="button" id="fbtn">Follow</button>

I don't know where I went wrong, in theory this looks fine to me but I am new to jquery and ajax and I must have missed something.

MG91
  • 193
  • 1
  • 11
  • use event delegation use `.on()` – guradio Feb 01 '18 at 09:04
  • 1
    Possible duplicate of [Event binding on dynamically created elements?](https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – guradio Feb 01 '18 at 09:04
  • Share the HTML code please. – ADreNaLiNe-DJ Feb 01 '18 at 09:05
  • You are looking for element with an ID and binding an event. Event will remain although you change his ID. You will need to [unbind](http://api.jquery.com/unbind/) that event on the element before binding another one. – Roms Feb 01 '18 at 09:06
  • @guradio am I using .on(click) wrong? I am not sure – MG91 Feb 01 '18 at 09:13
  • Why not just use one event with a condition inside. you can use `.data()` to store information. No need to change `id`s – Eddie Feb 01 '18 at 09:14
  • Bind the event to dom that is loaded like '$(document).on()' – guradio Feb 01 '18 at 09:15

5 Answers5

2

Instead of changing ID and writing JS for that, you rather just change class and use that class in code:

$("#fbtn").on('click', function() {
  var fbtn = $(this);
  if (fbtn.hasClass('follow')) {
    fbtn.removeClass('follow').addClass('unfollow');
    fbtn.text('Unfollow');
  } else {
    fbtn.removeClass('unfollow').addClass('follow');
    fbtn.text('Follow');
  }
  console.log('New Class: ' + fbtn.attr('class'));
  /*$.ajax({
    url: '/follow-unfollow',
    method: 'DELETE',
    success: function(response, err) {
      if (err) {
        console.log(err);
      }
      console.log("Unfollowd")
    }
  });
  */
});
.follow {
  background: red;
}

.unfollow {
  background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button style="width:100px;" class='follow' type="button" id="fbtn">Follow</button>
Milan Chheda
  • 8,159
  • 3
  • 20
  • 35
1

Event binding for dynamic crated elements concept

$('body').on('click','#fbtn',function(){ 
    var fbtn = $('#fbtn');
    var followee_name = $('#author').text();

        
            console.log("Followed")
            fbtn.text('Unfollow');
            fbtn.attr('id','unfollow');
});

$('body').on('click',"#unfollow",function(){ 
    var unfollowbtn = $('#unfollow');
            console.log("Unfollowd")
            unfollowbtn.text('Follow');
            unfollowbtn.attr('id','fbtn');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>

<button style="width:100px;" type="button" id="fbtn">Follow</button>
sTx
  • 1,213
  • 13
  • 32
1

Instead of using direct event binding you can do something like this

$('body').on('click', "#unfollow", function(){ 
var unfollowbtn = $('#unfollow');
    $.ajax({
        url: '/unfollow',
        method: 'DELETE',
        //dataType: 'application/json',
        success: function(response,err){ 
        if(err){
            console.log(err);
        }
        console.log("Unfollowd")
        unfollowbtn.text('Follow');
        unfollowbtn.attr('id','fbtn');
        }
    });
});

and

$('body').on('click', "#fbtn", function(){ 
var fbtn = $('#fbtn');
var followee_name = $('#author').text();

    $.ajax({
        url: '/follow',
        method: 'POST',
        //dataType: 'application/json',
        data:{followee_name:followee_name},
        success: function(response){ 
        console.log("Followed")
        fbtn.text('Unfollow');
        fbtn.attr('id','unfollow');
        }
    });
});
Shubham Agrawal
  • 417
  • 3
  • 11
  • Yes! this worked, so after 4 hours trying to figure this out, my mistake was with the on(click) event. Thank you so much @Shubham ! – MG91 Feb 01 '18 at 09:23
1

I know this is not what you are asking. This is just an alternative solution.

You can just have one event and just a switch inside.

You can store the status using .data()

$(document).ready(function(){
 
 $( "#follow-action" ).click(function(){
  var action = $(this).data("action");

  switch( action ) {
   case "follow":
    $(this).data("action", "unfollow");
    $(this).text('Unfollow');
    
    /*
     Put your follow actions here.. ajax etc
    */

    break;
   case "unfollow":
    $(this).data("action", "follow");
    $(this).text('Follow');
    
    /*
     Put your unfollow actions here.. ajax etc
    */
    
    break;
  }
 });
 
 //console.log();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<button type="button" id="follow-action" data-action="follow">Follow</button>
Eddie
  • 26,593
  • 6
  • 36
  • 58
1

As others have stated, the time when the click handlers are added means that the "unfollow" handler would likely never get triggered and would just result in the "follow" handler running after every click.

However I'm not sure this is the best way to do what you want. Why not just have two buttons with one hidden. Toggling the visibility of the buttons which is likely way quicker than modifying the button.

$(document).ready(function() {
  $('#follow').on('click', function() {
    // do something with AJAX
    $('#followButtons').addClass('following');
  });

  $('#unfollow').on('click', function() {
    // do something with AJAX
    $('#followButtons').removeClass('following');
  });
});
#followButtons.following #follow {
  display: none;
}

#unfollow {
  display: none;
}

#followButtons.following #unfollow {
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="followButtons" class="">
  <button id="follow" type="button">Follow</button>
  <button id="unfollow" type="button">Unfollow</button>
</div>
phuzi
  • 12,078
  • 3
  • 26
  • 50