Ajax bind click to another element - javascript

I have a button (is anchor tag with class vote) which should be clicked to vote for an article via ajax request. After that I want to update the votes count in my blade view (its a laravel application). The div with the class points should be updated but I dont know how to bind points on click to the ajax call?
I want to bind the .point to ajax call like I did it with $button to then update the div with the class points.
<a data-id="{{ $article->id }}" class="btn vote {{ Auth::check() && Auth::user()->votedFor($article) ? 'btn-success' : '' }}"></a>
Main code:
<div data-id="{{ $article->id }}" class="points">{{ $article->votes->count() }}</div>
$(document).on('click','.vote',function(){
var $counter = $(this).next();
var $button = $(this);
var id = $button.data('id');
var token = $('meta[name="csrf-token"]').attr('content');
$.ajax({
type:'POST',
url:"{!! URL::to('article/vote/') !!}/" + id,
dataType: 'JSON',
data: {
"_method": 'POST',
"_token": token,
"id": id,
},
success:function(data){
$counter.html(data.count);
var color = data.voted ? '#bbb' : '#38c172';
$button.css('background-color', color);
console.log('success');
console.log(data);
},
error:function(xhr){
if (xhr.status == 401) {
window.location.href = "{!! URL::to('login') !!}";
} else if (xhr.status == 403) {
window.location.href = "{!! URL::to('email/verify') !!}";
}
},
});
});

So you want your .points to be updated and not the a button you clicked.
First, make sure your a and .points are children of the same div element and there like:
<div>
<a data-id="{{ $article->id }}" class="btn vote {{ Auth::check() && Auth::user()->votedFor($article) ? 'btn-success' : '' }}">
button
</a>
<div data-id="{{ $article->id }}" class="points">
{{ $article->votes->count() }}
</div>
</div>
...
<div>
<a data-id="{{ $article->id }}" class="btn vote {{ Auth::check() && Auth::user()->votedFor($article) ? 'btn-success' : '' }}">
button
</a>
<div data-id="{{ $article->id }}" class="points">
{{ $article->votes->count() }}
</div>
</div>
Then in your JavaScript define the counter element like
var $counter = $(this).parent().find('points');
and update your success: method to apply CSS class and put data count:
$counter.html(data.count);
var color = data.voted ? '#bbb' : '#38c172';
$counter.css('background-color', color);
Let me know if it makes sense and you can finish the implementation.

Related

Update quantity of cart after add product to cart AJAX / Django without refreshing page?

The product is successfully added in the cart but the cart value is not up to date. I will have to refresh the page so that the div is up to date. I tried the load() and html() methods but anything will happened.
How to refresh cart container when I add the product to the cart ?
I need a help please.
Views Django
def add_cart(request, product_id):
cart = Cart(request)
product = get_object_or_404(Product, id=product_id)
form = CartProductForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
cart.add(product=product,
quantity=cd['quantity'],
update_quantity=cd['update_qt']
)
return JsonResponse({'status': 'success'})
Form
from django import forms
from django.core.validators import MinValueValidator, MaxValueValidator
class CartProductForm(forms.Form):
quantity = forms.IntegerField(initial=1)
update_qt = forms.BooleanField(required=False, initial=False, widget=forms.HiddenInput)
HTML Form Code
<form action="{% url "..." %}" method="post" data-id="{{ ... }}" class="form-order" id="form">
{{ cart_product_form }}
{% csrf_token %}
<a data-id="{{ ... }}" class="buy-product"><button>BUY</button></a>
</form>
HTML Span
<ul class="navbar-nav ml-auto d-block d-md-none">
<li class="nav-item">
<a class="btn btn-link" href="#"><i class="bx bxs-cart icon-single"></i> <span class="badge badge-danger" id="cartval">{{ cart | length }}</span></a>
</li>
</ul>
JS Code
$(".form-order").on('submit', function(e){
e.preventDefault();
var product_id = $(this).attr('data-id')
var quantity = $(this).find("#id_quantite").val()
console.log(product_id)
console.log(quantity)
data = {
'product_id': product_id,
'quantity': quantity
}
var point='/cart/add/'+product_id+'/'
$.ajax({
headers:{
'Content-Type':'application/json',
'X-CSRFToken':csrftoken,
},
url: point,
type: 'POST',
dataType: 'json',
data: data,
success: function(data){
$("cartval").load();
$("#cartval").load(location.href + " #cartval");
}
})
})

Displaying comments using Ajax

i am working on a project using Django. There are lists of users posts in homepage and each post has a comment form. I was able to implement comment properly on views, but the issue now is when I submit a comment it display empty string instead of the comment, the comment display in chrome console. How do i display comment on each post by user when a form is submitted. I attached an image to my questioin to clarify my question.
home.html
<div id="newfeeds-form">
{% include 'ajax_newfeeds_comments.html' %}
</div>
ajax_newfeeds_comments.html
<!-- New Feeds comment Text -->
{% for post in all_images %}
<div class="container newfeeds-comment" id="display-comment">
{% for comment in post.comments_set %}
<div class="row">
<div class="col-1 col-md-1 col-lg-1">
{% if comment.user.profile.profile_pic %}
<img src="{{ comment.user.profile.profile_pic.url }}" class="d-flex rounded-circle" alt="image" height="28" width="28">
{% endif %}
</div>
<div class="col-10 col-md-10 col-lg-10 p-2 ml-1" id="user-commentpost">
<span class="comment-post truncate">
<span class="name text-lowercase">{{ comment.user }}</span>
{{ comment.comment_post }}</span>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
<span class="md-form">
<form enctype="multipart/form-data" class="feeds-form form-inline md-form form-sm" method="POST" action="{% url 'site:home' %}" id="newfeeds-form{{ post.id }}">
{% csrf_token %}
<input type="hidden" value={{post.id}} name="post_comment">
<img src="{{ request.user.profile.profile_pic.url }}" class="rounded-circle avatar-img" height="28" width="28">
<textarea name="comment_post" class="textinput textInput animated fadeIn" placeholder="Add a comment..." required="" id="id_comment_post{{ post.id }}" onkeyup=""></textarea>
<button type="submit" class="submit" id="submit1-{{post.id}}"><i class="fas fa-paper-plane"></i></button>
</form
</span>
Views:
def home_view(request):
#All posts in new feed
all_images = Post.objects.filter(
Q(poster_profile=request.user, active=True)|
Q(poster_profile__from_user__to_user=request.user, active=True)|
Q(poster_profile__to_user__from_user=request.user, active=True)|
Q(poster_profile__profile__friends__user=request.user, active=True)).distinct().exclude(
Q(hide_post=request.user, active=True)|
Q(poster_profile__profile__blocked_users__user=request.user, active=True))
#Comment form homepage
if request.method == 'POST':
post_id = request.POST.get("post_comment")
post_obj = Post.objects.get(pk=post_id)
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.user = request.user
comment.commented_image = post_obj
comment.save()
# messages.info(request,'You submitted a comment')
#return redirect('/')
else:
form = CommentForm()
context = {
'form': form,
'all_images': all_images,
}
if request.is_ajax():
html = render_to_string('ajax_newfeeds_comments.html', context, request=request)
return JsonResponse({'form': html})
return render(request,'home.html', context)
Ajax:
<script type="text/javascript">
//HomeFeeds Comment
$(document).ready(function() {
$('.feeds-form').on('submit', onSubmitFeedsForm);
$('.feeds-form .textinput').on({
'keyup': onKeyUpTextInput,
'change': onKeyUpTextInput
});
function onKeyUpTextInput(event) {
var textInput = $(event.target);
textInput.parent().find('.submit').attr('disabled', textInput.val() == '');
}
function onSubmitFeedsForm(event) {
event.preventDefault();
console.log($(this).serialize());
var form = $(event.target);
var textInput = form.find('.textinput');
var hiddenField = form.find('input[name="post_comment"]');
$.ajax({
type: 'POST',
url: "{% url 'site:home' %}",
data: form.serialize(),
dataType: 'json',
beforeSend: function() {
form.find('.submit').attr('disabled', true);
},
success: function(response) {
$('#newfeeds-form' + hiddenField.val()).html(response.form);
textInput.val('');
var numberOfCommentsElement = $('#number-of-comments');
numberOfCommentsElement.text(parseInt(numberOfCommentsElement.text()) + 1);
},
error: function(rs, e) {
console.log(rs.resopnseText);
},
complete: function() {
textInput.trigger('change');
}
});
}
});
</script>
You don't need ajax actually, you can simply:
let value = $('myInput').val();
$('myCommentContainer').prepend(`
Format the comment as you want ${value}
`)
$('myInput').val('') // To empty the value
now call the ajax normally:
$({
type: 'POST',
url: "{% url 'site:home' %}",
data: form.serialize(),
dataType: 'json',
beforeSend: function() {
form.find('.submit').attr('disabled', true);
},
success: function(response) {}
})
Done, leave the success empty
appending it within the ajax success will make it slower anyway!

Change status with ajax in laravel

I'm using Laravel in my project. I have a voucher that maintains a status.
I've used AJAX for changing the status and the AJAX code works successfully.
However the status did not change in my view until after I refresh the page. I'm looking for a way to solve this issue.
<button class="btn btn-link p-0 change" type="submit" data-id="{{ $voucher->id }}">
#if ($voucher->status == 1)
<i class="fa fa-toggle-on text-success"></i>
#else
<i class="fa fa-toggle-off text-muted"></i>
#endif
</button>
#if ($voucher->status == 1)
<span class="badge badge-soft-success">
enable
</span>
#else
<span class="badge badge-soft-pink">
disbale
</span>
#endif
$(".change").click(function() {
var id = $(this).data("id");
$.ajax({
url: "vouchers/change-status/" + id,
type: 'put',
dataType: "JSON",
data: {
"id": id,
"_method": 'put',
"_token": "{{ csrf_token() }}",
},
success: function() {
console.log("it Work");
// $("tr#"+id).remove();
}
});
console.log("It failed");
});
You can try this way:
Blade
Wrap your code in some holder with class status-enabled, when status is 1. Set special classes for elements which will be visible or not according status.
<div class="holder #if($voucher->status == 1) status-enabled #endif">
<button class="btn btn-link p-0 change" type="submit" data-id="{{ $voucher->id }}">
<i class="fa fa-toggle-on text-success enabled-visible"></i>
<i class="fa fa-toggle-off text-muted enabled-invisible"></i>
</button>
<span class="badge badge-soft-success enabled-visible">
enable
</span>
<span class="badge badge-soft-pink enabled-invisible">
disbale
</span>
</div>
CSS
Set rules:
.holder .enabled-visible {
display: none;
}
.holder .enabled-invisible {
display: inline-block;
}
.holder.status-enabled .enabled-visible {
display: inline-block;
}
.holder.status-enabled .enabled-invisible {
display: none;
}
JS
Toggle holder class when you have successfuly change status.
$(".change").click(function() {
var id = $(this).data("id");
$.ajax({
url: "vouchers/change-status/" + id,
type: 'put',
dataType: "JSON",
data: {
"id": id,
"_method": 'put',
"_token": "{{ csrf_token() }}",
},
success: function() {
$(this).closest('.holder').toggleClass('status-enabled');
}
});
console.log("It failed");
});
Just in your success function:
success: function() {
console.log("it Work");
$("i.fa-toggle-on).hide();
$("i.fa-toggle-off).show();
}
Html Tag no need of if condition php blade.
<button class="btn btn-link p-0 change" type="submit" data-id="{{ $voucher->id }}">
#if ($voucher->status == 1)
<i class="fa fa-toggle-on text-success"></i>
#else
<i class="fa fa-toggle-off text-muted"></i>
#endif
</button>
<div id="alert-message"></div> // add this line
#endrole
change this code into your code.
script file
$(".change").click(function() {
var id = $(this).data("id");
var success = '<span class="badge badge-soft-success">' +
'enable' +
'</span>';
var failed = '<span class="badge badge-soft-pink">' +
'disbale' +
'</span>';
$.ajax({
url: "vouchers/change-status/" + id,
type: 'put',
dataType: "JSON",
data: {
"id": id,
"_method": 'put',
"_token": "{{ csrf_token() }}",
},
success: function() {
console.log("it Work");
$('#alert-message').html(success);
// $("tr#"+id).remove();
}
});
$('#alert-message').html(failed);
});

Using Ajax change state of a clicked button

I am building a page in a Django project which has multiple comments each of which can be liked/unliked with a button next to the text. So the page has multiple like/unlike buttons.
The buttons display fine when the page is loaded, and I can use Ajax to send data to Django and update my database which works fine, and I can return data back to the Ajax success function.
What I can't work out is - how can I update the status of the actual button which was clicked. I am able to update the status of all of the buttons together on the page as per the code below (pointless I know!), but can't see how I reference the clicked button. I've tried passing and then returning the button id which I can display in an alert, but not sure if this is what I should be using or where I go from here?
HTML Template
{% for comments in comments_page %}
<p>
<b>{{ comments.created_at }} ({{ comments.user_type }})</b>
{% if comments.comment_liked is False %}
<button class="comment btn btn-primary btn-xs"
id={{ forloop.counter0 }}
data-surveyid="{{ comments.id }}"
data-commentliked="True"
type="button">
<span class="glyphicon glyphicon-star-empty"></span>
</button>
{% else %}
<button class="comment btn btn-success btn-xs"
id={{ forloop.counter0 }}
data-surveyid="{{ comments.id }}"
data-commentliked="False"
type="button">
<span class="glyphicon glyphicon-star"></span>
</button>
{% endif %}
</p>
<p>{{ comments.comments }}</p>
<br>
{% endfor %}
Javascript / Ajax
{% block javascript %}
<script type="text/javascript">
$(function() {
$('.comment').click(function() {
var surveyid, commentliked, buttonid;
surveyid = $(this).attr('data-surveyid');
commentliked = $(this).attr('data-commentliked');
buttonid = $(this).attr('id');
$.ajax({
url: '/evaluations/validate_username/',
data: {
'surveyid': surveyid,
'commentliked': commentliked,
'buttonid': buttonid
},
dataType: 'json',
type: 'get',
success: function (data) {
alert(data.buttonid);
$(".comment").removeClass('comment btn btn-primary btn-xs').addClass('comment btn btn-success btn-xs');
}
});
});
});
</script>
{% endblock %}
Just target the clicked button in your success function:
{% block javascript %}
<script type="text/javascript">
$(function() {
$('.comment').click(function() {
// the button instance that was clicked
var clickedBtn = $(this);
var surveyid, commentliked, buttonid;
// also, you can use data-* to get the data attributes
// surveyid = clickedBtn.attr('data-surveyid');
// commentliked = clickedBtn.attr('data-commentliked');
surveyid = clickedBtn.data('surveyid');
commentliked = clickedBtn.data('commentliked');
buttonid = clickedBtn.attr('id');
$.ajax({
url: '/evaluations/validate_username/',
data: {
'surveyid': surveyid,
'commentliked': commentliked,
'buttonid': buttonid
},
dataType: 'json',
type: 'get',
success: function (data) {
alert(data.buttonid);
clickedBtn.removeClass('comment btn btn-primary btn-xs')
.addClass('comment btn btn-success btn-xs');
}
});
});
});
</script>
{% endblock %}

Get an specific value in <a> html with javascript-ajax Django

I'm using Django and Python 3.
I have this in my HTML code:
{% for category in categories() %}
<li class="c-menu__item fs-xsmall">
<a href="#" id="next-category">
{{ category}}
</a>
</li>
<input type="hidden" value="{{ category.code }}" id="category-id">
{% endfor %}
<div class="col-xs-4" id="sub_categories">
</div>
That lists few categories.
And I have this in my script:
$( document ).on( 'click', '#next-category', function(e){
e.preventDefault();
$.ajax({
url : 'product_category/addAjax',
type : 'POST',
data : {
category: $( '#category-id').val(),
},
})
.fail(function( jqXHR, textStatus, errorThrown ){
console.log('FAIL');
})
.done(function(data){
console.log('DONE');
$('#sub_categories').prop('innerHTML',data["sub_categories"]);
});
return false;
});
When I print: $( '#category-id').val(), I always get the same value. It doesn't matter if I choose the first category listed or the last one, I will always get the same value. I have no idea what's wrong.
Gocht comment is the correct answer.
Since you want to iterate over tags they should have different id's !!!
The simple work around is to use a class and evaluate correct id:
{% for category in categories() %}
<li class="c-menu__item fs-xsmall">
<a href="#" class="next-category" value="{{ forloop.counter }}" >
{{ category}}
</a>
</li>
<input type="hidden" value="{{ category.code }}" id="category-id-{{ forloop.counter }}">
{% endfor %}
<div class="col-xs-4" id="sub_categories">
</div>
script :
$( document ).on( 'click', '.next-category', function(e){
e.preventDefault();
var id = $(this).attr("value");
var input_id = "#category-id-" + id;
$.ajax({
url : 'product_category/addAjax',
type : 'POST',
data : {
category: $(input_id).val(),
},
})
.fail(function( jqXHR, textStatus, errorThrown ){
console.log('FAIL');
})
.done(function(data){
console.log('DONE');
$('#sub_categories').prop('innerHTML',data["sub_categories"]);
});
return false;
});

Categories