Jand
Jand

Reputation: 2727

How apply ajax function on specific div?

In a simple forum app, I have a topic page which contains multiple posts. On each post there is Like widget divs like this:

<ul>
    <li>
        <p id="plike_count{{post.id}}"> {{  post.likes }}</p> 
    </li>

    <li>
            {% if user.is_authenticated %}
                <span data-type=" post" title="Like">       {% csrf_token %}
              <i class="thumbs-up" id="likep" name="{{ post.id}}"> </i>           
            {% endif %}
    </li>

</ul>

And here is the ajax Like snippet that is supposed to capcher each Like and update the like counts:

$(function(){
$('#likep').click(function(){
      $.ajax({
               type: "POST",
               url: "/forum/post/like/",
               data: {
               'post_id': $(this).attr('name'), 
               'csrfmiddlewaretoken': '{{csrf_token}}'
               },


               success: plikeSuccess,
               dataType: 'html'

                });
    });

});
function plikeSuccess(data, textStatus, jqXHR)
{
    $('#plike_count').html(data);    
}

A very similar ajax code works fine when there is only one post/div to work with but I don't know how to generalize the code for multiple posts.

So the problem is how make an id corresponding to plike_count{{post.id}} in ajax?

I've tried $('#plike_count'.conc(post_id)).html(data); instead of $('#plike_count').html(data); but it did not work.

Upvotes: 0

Views: 71

Answers (3)

max
max

Reputation: 102222

The trick is to use the context from the original click event in your ajax callback.

We do this by creating a variable within the click handler which binds the context. Also note that we use the fact that all the jQuery ajax methods return a promise object.

Instead of passing a named function to the success option we instead call the .done method on the promise. Many would say that creating a named function in the global namespace for a jQuery callback is a huge antipattern.

Note that we also use a bit more structured html so that we treat the likes as a reusable module of code.

$('.like').on('click', function(e){
  var $btn = $(this);
  var promise = $.post({
    url: $btn.attr('href'),
    data: {
      id: $btn.data('id'),
      csrfmiddlewaretoken: '{{csrf_token}}'
    },
    dataType: 'html'
  });
  promise.done(function(jqXHR){
    $btn.parents('.like-module')
       .find('.like-counter')
       .html(jqXHR.responseText());
  });
  e.preventDefault(); // prevent following link.
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="post">
  <aside class="like-module">
    <div class="like-counter">0</div>
    <a href="/forum/post/like/" class="like" data-id="{{ post.id }}">like</div>
  </aside>
</div>

<!-- more posts --!>

Added.

Also I belive a more RESTful design would be:

POST /forum/posts/:id/likes # to like a post
DELETE /forum/posts/:id/likes # to unlike a post

POST /forum/post/likes smells like a procedure and not something which acts on a resource.

Upvotes: 1

davcs86
davcs86

Reputation: 3935

Use

$(function(){
    $('#likep').click(function(){
        var _self = this;
        $.ajax({
           type: "POST",
           url: "/forum/post/like/",
           data: {
           'post_id': $(this).attr('name'), 
           'csrfmiddlewaretoken': '{{csrf_token}}'
        },
        success: function (data, textStatus, jqXHR)
        {
            $("#plike_count"+$(_self).attr('name')).html(data);    
        },
        dataType: 'html'

        });
    });
});

Upvotes: 1

SLaks
SLaks

Reputation: 887767

You're looking for the wonders of the + operator, which concatenates strings:

"a" + b

Upvotes: 1

Related Questions