Update like count span in same duplicate post

Viewed 80

I have a duplicate list of posts on the same page. Hence, some posts appear on the same page more than once.

The like system updates through javascript the like count of a post in a span, with id "like-{{ $item->id }}", it is identified with the post id.

<span id="like-{{ $item->id }}">
    @json($item->likers()->count())
</span>

When a post is liked, only one post card is updated, the others are not, despite having the same id.

How can I solve this annoyance?

function likePost(a) {
  $.ajaxSetup({
    headers: {
      "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content")
    }
  });
  $(this);
  $.ajax({
    url: APP_URL + "/save_like",
    type: "POST",
    dataType: "json",
    data: {
      item: a,
      _token: $('meta[name="csrf-token"]').attr("content")
    },
    success: function(e) {
      var t;
      1 == e.bool ? ($("#like-icon-" + a).removeClass("text-muted").addClass("icon-filled text-danger"), t = $("#like-" + a).text(), $("#like-" + a).text(++t)) : 0 == e.bool && ($("#like-icon-" + a).removeClass("icon-filled text-danger").addClass("text-muted"), t = $("#like-" + a).text(), $("#like-" + a).text(--t))
    },
    error: function(e) {
      location.replace(APP_URL + "/login")
    }
  })
};
<a href="javascript:void(0);" onclick="likePost({{ $item->id }})" class="btn btn-light border-0"><svg xmlns="http://www.w3.org/2000/svg" id="like-icon-{{ $item->id }}" class="icon @if(Auth::check()) @if(Auth::user()->hasLiked($item)) icon-filled text-danger @else text-muted @endif @else text-muted @endif" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M19.5 13.572l-7.5 7.428l-7.5 -7.428m0 0a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572" /></svg> <span id="like-{{ $item->id }}">@json($item->likers()->count())</span></a>


Changes applied:

<a href="#" class="btn btn-light border-0">
     <svg xmlns="http://www.w3.org/2000/svg" id="like-icon-{{ $item->id }}" class="icon  icon-filled text-danger" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M19.5 13.572l-7.5 7.428l-7.5 -7.428m0 0a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572" /></svg> 
     <span id="like-{{ $item->id }}">
          @json($item->likers()->count())
     </span>
</a>

And the java code you provided. It shows no errors, but it doesn't work.


In order not to be fully explained in my intent, I leave some pictures on my problem.

I have a tab that fetches all the categories and posts within them, consequently some posts are duplicated, but by clicking like the first of the posts is updated (the like count) while in the other cards it is not.

enter image description here

enter image description here


enter image description here


enter image description here

enter image description here

2 Answers

Need more info. How are you updating through JavaScript?

If you're using getElementById or so, the problem here is it only returns the first element that satisfies the query not all the elements with the same id on the page. Use a class, that way you can use querySelectorAll and loop through it and do the necessary updates.

HTML:

<span id="like-{{ $item->id }}" class="post-{{ $item->id }}">
    @json($item->likers()->count())
</span>

JS:

const setLikes = postID => {
  const postElems = document.querySelectorAll(`.post-${postID}`);
  // loop through all the posts
  for(let i = 0; i < postElems.length; i++){
    // use the logic here to update the like counts as you want
  }


}

Try this

  1. change <span id="like-{{ $item->id }}"> to
    <span class="likes" data-id="{{ $item->id }}">

  2. Change the link code to this - Add the ID to the link and not to the SVG or span

<a href="#"  id="like-{{ $item->id }}" class="like-link btn btn-light border-0">
  <svg ... /></svg> <span>1 like</span>
</a>

$.ajaxSetup({
  headers: {
    "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content")
  }
});

$("a[id^=like]").on("click", function() {
  const $link = $(this);
  const a = $link.attr("id").split("-")[1]; // make id="like-1234" into 1234
  console.log(a)
  
  /* Commented to test this snippet. uncomment in working code
  
  $.ajax({
    url: APP_URL + "/save_like",
    type: "POST",
    dataType: "json",
    data: {
      item: a,
      _token: $('meta[name="csrf-token"]').attr("content")
    },
    success: function(e) {
      const liked = e.bool == 1;
      */
      const liked = 1; // test, remove when using ajax
      $(".likes[data-id="+a+"]").each(function() {
        $(this)
          .toggleClass("text-muted", !liked)
          .toggleClass("icon-filled text-danger", liked)
        let t = +$(this).text();
        t += liked ? 1 : -1
        if (t<0) t=0; // remove if you support negative likes
        $link.find("span").text(t);
        $(this).html($link.html());

      })
    /* },
    error: function(e) {
      location.replace(APP_URL + "/login")
    }
  }) */
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="likes" data-id="1234">
        1
    </span><br/>
<span class="likes" data-id="1234">
        1
    </span>
<hr>


<a href="#" id="like-1234" class="like-link btn btn-light border-0"><svg xmlns="http://www.w3.org/2000/svg" class="icon  icon-filled text-danger" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M19.5 13.572l-7.5 7.428l-7.5 -7.428m0 0a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572" /></svg> <span>1</span></a>

Related