casualhuman
casualhuman

Reputation: 193

Font awesome Icon not asynchronously changing with an a change in class using Ajax

I have a love button (made with font awesome Icon) that should change every time a user clicks on it but when I click on it, it only changes eg from full solid to empty when I reload the page.

To change the Icon, the approach I use is changing the font awesome class on every click

exact part responsible for the button behavior

if (previous_action == 'like')
{
    $(event.target).find("i").removeClass("far fa-heart").addClass("fas fa-heart")
}
            
else {
    $(event.target).find("i").removeClass("fas fa-heart").addClass("far fa-heart")
     }

full code

$('a.like').on('click', function(event){
    event.preventDefault();
    event.stopPropagation();
    event.stopImmediatePropagation();

    $.post('{% url "posts:post_like" %}',
      {
        id: $(this).data('id'),
        action: $(this).data('action')
      },
      function(data){
        if (data['status'] == 'ok')
        {
            var previous_action = $(event.target).data('action');
            

            // toggle data-action
            $(event.target).data('action', previous_action == 'like' ?
            'unlike' : 'like');

            
            // toggle class to change icon
            if (previous_action == 'like')
            {
                $(event.target).find("i").removeClass("far fa-heart").addClass("fas fa-heart")
            }
            
            else {
                $(event.target).find("i").removeClass("fas fa-heart").addClass("far fa-heart")
            }
            
            
            // update total likes
            var previous_likes = parseInt($(event.target).closest("div").find("span.count .total").text());
            $(event.target).closest("div").find("span.count .total").text(previous_action == 'like' ? previous_likes + 1 : previous_likes - 1);
        }
      }
    );
  });

html extract

{% for post in posts %}
       <a href="{{ post.get_absolute_url}}" class="text-dark">
            <div class="d-flex bg-white pt-3 pl-2">
                    
    
                <div class=" p-2 mb-2">
                   {% with total_likes=post.users_like.count users_like=post.users_like.all %}
                            
                   <span class="count">
                       <span class="total">{{ total_likes }}</span> like{{ total_likes|pluralize }}
                            
                    </span>

                        
                    <p>
                        <span class="mr-5 ">
                            <a href="" data-id="{{ post.id }}" 
                                    data-action="{% if request.user in users_like %}un{% endif %}like" 
                                    class="like">

                                {% if request.user not in users_like %}
                                    <i class="far fa-heart"></i>
                                {% else %}
                                   <i class="fas fa-heart"></i>
                                {% endif %}
                            </a>
                        </span>
                    </p>
                    {% endwith %}
                </div>
            </div>
        </a>
{% endfor %}

Links extract

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.1.0/css/v4-shims.min.css">

Upvotes: 1

Views: 332

Answers (1)

Swati
Swati

Reputation: 28522

In your current code has you have use $(event.target) so when you click on i tag current target will be i tag and it doesn't have data-action attribute that's the reason your code doesn't work. Instead you can check if the event.target.tagName is a tag or not using this you can modify our selector .

Demo Code :

$('a.like').on('click', function(event) {
  event.preventDefault();
  event.stopPropagation();
  event.stopImmediatePropagation();
  //your ajax calll..
  //other codes ..
  //check if the event target elemnt is `a` tag or not 
  var target = event.target.tagName.toLowerCase() === 'a' ? $(event.target) : $(event.target).closest("a")
  //use target then..
  var previous_action = target.data('action');
  console.log(previous_action)
  target.data('action', previous_action == 'like' ?
    'unlike' : 'like');
  if (previous_action == 'like') {
    target.find("i").removeClass("fas fa-heart").addClass("far fa-heart")
  } else {
    target.find("i").removeClass("far fa-heart").addClass("fas fa-heart")
  }
  var previous_likes = parseInt($(event.target).closest("div").find("span.count .total").text());
  $(event.target).closest("div").find("span.count .total").text(previous_action == 'like' ? previous_likes + 1 : previous_likes - 1);

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.1.0/css/v4-shims.min.css">
<a href="{{ post.get_absolute_url}}" class="text-dark">
  <div class="d-flex bg-white pt-3 pl-2">
    <div class=" p-2 mb-2">
      <span class="count">
         <span class="total">12</span>
      </span>
      <p>
        <span class="mr-5 ">
<a href="" data-id="1" 
   data-action="like" 
   class="like">Like
 <i class="fas fa-heart"></i>
</a>
</span>
      </p>
    </div>
  </div>
</a>
<a href="{{ post.get_absolute_url}}" class="text-dark">
  <div class="d-flex bg-white pt-3 pl-2">
    <div class=" p-2 mb-2">
      <span class="count">
         <span class="total">74</span>
      </span>
      <p>
        <span class="mr-5 ">
<a href="" data-id="2" 
   data-action="unlike" 
   class="like">Unlike
<i class="far fa-heart"></i>
</a>
</span>
      </p>
    </div>
  </div>
</a>

Upvotes: 1

Related Questions