Reputation: 2727
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
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 --!>
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
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
Reputation: 887767
You're looking for the wonders of the +
operator, which concatenates strings:
"a" + b
Upvotes: 1