Get an ID just created without reloading the page - javascript

Here is a div that I append in AJAX with a script (at the bottom of the TWIG file) :
<div>
{% for vote in proposal.votes %}
{% if app.user == vote.user %}
<a href="{{ path('vote_delete',{'proposal' : proposal.id, 'vote' : vote.id}) }}"
class="btn btn-light ml-1 btn-sm">
</a>
{% endif %}
{% endfor %}
</div>
If I then click on the freshly appended button, it returns an error because the ID "vote.id" is still 0 until I reload the page and the ID gets found...
Is there a way to trigger the for loop without reloading the page to get the ID directly after its creation? Is it linked with "async" or any "ready" function?
EDIT :
The script that appends the div #deleteVote when I vote :
$(document).on('click', '.votedFullAgreement', function (event){
event.preventDefault();
$.ajax({
url: '{{ path('vote_add', {'slug' : slug, 'proposal' : proposal.id, 'userVote' : 'votedFullAgreement', 'user' : app.user.id }) }}',
type: 'POST',
dataType: 'html',
success: function (){
if( $('#deleteVote').length === 0 ) {
//The whole HTML of the div
},
error: function (resultat, statut, erreur) {
console.error(erreur);
}
});
});
The #deleteVote that gets appended, with the url of the "deleteVote" function (which needs to know the ID of the vote to delete) :
$(document).on('click', '.deleteVote', function (event){
event.preventDefault();
$.ajax({
url: '{{ path('vote_delete', {'slug' : slug, 'proposal' : proposal.id, 'vote' : vote.id }) }}',
type: 'POST',
dataType: 'html',
success: function (){
$('#deleteVote').slideUp();
},
});
});

As I've mentioned in the comments, you can't pass a javascript directly to twig, as twig is rendered serverside. One way to solve this is to calculate all the path beforehand:
{% for vote in proposal.votes %}
...
<button type="button" class="votedFullAgreement" data-path="{{ path('vote_add', {'slug' : slug, 'proposal' : proposal.id, 'userVote' : 'votedFullAgreement', 'user' : app.user.id }) }}">Add vote</button>
...
{% endfor %}
Now you can access the path directly in javascript
$(document).on('click', '.votedFullAgreement', function (event){
event.preventDefault();
$.ajax({
url: $(this).data('path'),
type: 'POST',
dataType: 'html',
success: function (){
if( $('#deleteVote').length === 0 ) {
//The whole HTML of the div
},
error: function (resultat, statut, erreur) {
console.error(erreur);
}
});
});
You could also make an extra request to a controller to generate the path, but this would mean you would need to pass all the variables, e.g. slug, app.user.id, ...
More information on how to generate a path inside a controller can be found here

Related

How to run a java script (or some) with ajax from a separate file?

I have several ajax scripts in the base body django template. I want to run them in a separate js file, but the scripts do not work from a file.
My script in the body template (this is a working code.):
<!--Add product to the cart after press Add button-->
<script>
$(document).on('click', '#add-button', function (e){
e.preventDefault();
var prodid = $('#add-button').val();
$.ajax({
type: 'POST',
url: '{% url "add_cart" %}',
data: {
product_id: $('#add-button').val(),
quantity: $('#qty').val(),
csrfmiddlewaretoken: '{{csrf_token}}',
action: 'POST'
},
success: function (json) {
document.getElementById('cart_icon_count').innerHTML = json.qty;
},
error: function(xhr, errmsg, err) {}
});
})
</script>
Than delete script from body and copy in js file:
my_js.js
$(document).on('click', '#add-button', function (e){
e.preventDefault();
var prodid = $('#add-button').val();
$.ajax({
type: 'POST',
url: '{% url "add_cart" %}',
data: {
product_id: $('#add-button').val(),
quantity: $('#qty').val(),
csrfmiddlewaretoken: '{{csrf_token}}',
action: 'POST'
},
success: function (json) {
document.getElementById('cart_icon_count').innerHTML = json.qty;
},
error: function(xhr, errmsg, err) {}
});
})
and in the body:
<script src="{% static 'js/my_js.js' %}"></script>
The usual java script function works this way, but for some reason this script does not.
Any ideas for running one or more of these scripts from a separate file?
Thank's qrsngky - you helped me figure it out 50% and guided me to the right solution!
{% url "add_cart" %} I replaced with "/cart/add_cart/".
Error 403 Forbidden - the problem was in csrftoken.
I add in my base.html
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
and in 'js/my_js.js' add csrfmiddlewaretoken: window.CSRF_TOKEN
Similar I put {% url "add_cart" %} in variable in the body.html.
And everything worked!

AJAX form submission in Django

I keep receiving 'Not Ajax' as a response during my form submission. I have to be missing something small but I cannot see it...
class VideoLikeView(View):
def post(self, request):
if request.is_ajax():
message = 'Ajax'
else:
message = 'Not Ajax'
return HttpResponse(message)
The AJAX code looks like this:
$(function () {
$("#like-form").submit(function (event) {
$.ajax({
type: "POST",
url: form.attr('action'),
headers: {'X-CSRFToken': '{{ csrf_token }}'},
data: {'pk': $(this).attr('value')},
success: function(response) {
alert('Video liked');
},
error: function(rs, e) {
alert(rs.responseText);
}
}
});
});
});
And my HTML:
<form id="like-form" action="{% url 'video-like' %}" method="post">
{% csrf_token %}
<input name="like"
type="hidden"
value="{{ video.id }}">
<button type="submit">
<span class="video-options ml-auto fas fa-heart fa-2x m-2"></span>
</button>
</form>
One question to add to this; how can I use an <input> in my form without using a <button>? I would like to use fontawesome icons but it seems I have to use a button to get the form to submit.
I found one answer on the internet that seems to work but I don't understand what the issue was. Seems like some type of serialization needed (?)... Anyways, here is what worked:
var frm = $('#like-form');
frm.submit(function () {
$.ajax({
type: frm.attr('method'),
url: frm.attr('action'),
data: frm.serialize(),
success: function (data) {
console.log('success');
},
error: function(data) {
console.log('failed');
}
});
return false;
});
Would love to hear from people why this works and not the previous..
try change your btn type button and add ID for event click :
since putting the submit button goes directly to view.py without going through AJAX
<form id="like-form" action="{% url 'video-like' %}" method="post">
{% csrf_token %}
<input name="like"
type="hidden"
value="{{ video.id }}" id="id_pk">
<button type="button" id="id_btn">
<span class="video-options ml-auto fas fa-heart fa-2x m-2"></span>
</button>
in your script
$("#id_btn").click(function() {
$.ajax({
url:window.location.origin + 'your url'
type: 'POST',
data: {'pk':$(#id_pk).val(), 'accion':'guardar'},
success: function (data) {
console.log('success');
},
error: function(data) {
console.log('failed');
}
});
});
and your view.py
def post(self, request):
if 'guardar' in request.POST['accion']:
print("")

How to delete a product with ajax

I want to delete this product instantly when I click the delete button, so far when I click the delete button it hides the icon and the product is still showing until I refresh the page then the product is gone, how can I fix this?
Script
function deleteFromFavourites(productid, userid) {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: 'post',
url: `product/${productid}/unlike`,
data: {
'user_id': userid,
'product_id': productid,
},
success: function () {
console.log($('#deletefavourite' + productid));
// show delete button
$('#deletefavourite' + productid).hide();
},
});
}
Blade file
#foreach (Auth::user()->likedProducts as $product)
<h4>USD {{$product->price }}</h4>
<h1>USD {{$product->name }}</h1>
<a style="display: {{$product->isLiked ? "" : "none"}}" id="deletefavourite{{$product->id}}" onClick="deleteFromFavourites({{$product->id}}, {{ Auth::user() ? Auth::user()->id : 0 }})">Delete</a>
#endforeach
You must change to parent div of the product you want to hide instead of hiding the 'a' tag.
function deleteFromFavourites(this, productid, userid) {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: 'post',
url: `product/${productid}/unlike`,
data: {
'user_id': userid,
'product_id': productid,
},
success: function () {
// remove parent division on success
this.parent().remove();
},
});
}
in your blade wrap the product into div.
#foreach (Auth::user()->likedProducts as $product)
<div id="parentDiv">
<h4>USD {{$product->price }}</h4>
<h1>USD {{$product->name }}</h1>
<a style="display: {{$product->isLiked ? "" : "none"}}" id="deletefavourite" data-user_id="{{ Auth::user() ? Auth::user()->id : 0 }}" data-product_id="{{$product->id}}">Delete</a>
</div>
#endforeach
Another workaround is to remove the onclick and add onclick function to your js.
$('#deletefovourite').click(function(){
deleteFromFavourites($(this), $(this).data('product_id'),$(this).data('user_id'));
})

pass controller with parameter in ajax symfony

I'm work with symfony for an E-commerce project. I have like to display a pop-up window in relation to each product. this pop-up window have a list choices. so for that I like to pass the controller for this window by Ajax to be dynamic , for that :
Code HTML
{% for p in products %}
<a id="#basket-modal" href="#" data-id="{{ p.id }}" data-toggle="modal" data-target="{{ modal }}" class="btn btn-primary">
{% endfor %}
Script
<script type="text/javascript">
$(document).ready(function(){
$("#basket-modal").on({ click: function() {
var op_prod_id = $(this).data('id');
$.ajax({
url: "{{ path('ajout_prod_panier', {'id': op_prod_id }) }}" ,
type: "POST",
data: "op_prod_id="+op_prod_id,
success: function(data, status, xhr) {
console.log(data);
},
error: function(jqxhr, status, error) {
console.log(error);
}
});
event.stopPropagation();
}
});
});
</script>
the problem that always I have an error message :
Variable "op_prod_id" does not exist.
in url:
"{{ path('ajout_prod_panier', {'id': op_prod_id }) }}"
var op_prod_id = $(this).data('id'); is a js variable.
{{ path('ajout_prod_panier', {'id': op_prod_id }) }} is a twig expression.
Try something like that:
<a href="#" data-id="{{ p.id }}" data-url={{ path('ajout_prod_panier', {'id': p.id}) }}" data-toggle="modal" data-target="{{ modal }}" class="basket-modal btn btn-primary">
and in your js
$(".basket-modal").on({ click: function() {
var op_prod_id = $(this).data('id');
var op_prod_url = $(this).data('url');
....
url: op_prod_url

Django returning None after request.POST.get

I'm new to Django and AJAX and I'm trying to send the ID of a dropdown list to the Django View with an ajax POST. This ID is then used in a queryset filter to return with AJAX the row, based off the ID. I'm getting stuck with applying the filter to the query set, as it seems to be posting the ID and then a variable with None. When I print to console the variable sent in the POST I get the ID, followed by none, e.g.:
1748
None
My HTML is:
<select id="drugSet">
{% for dose in dose_set %}
<option id="{{ dose.pubmed_id }}">{{ dose.drug_name }}</option>
{% endfor %}
</select>
<span id="drugName"></span>
Javascript:
function NeedDrugInformation() {
var elementID = document.getElementById("drugSet");
var strUser = elementID.options[elementID.selectedIndex].id;
$.ajax({
type: "POST",
url: "drugsanddoses/",
dataType: "text",
async: true,
data: { csrfmiddlewaretoken: '{{ csrf_token }}', drugID: strUser },
});
$.ajax({
type: "GET",
url: "drugsanddoses",
dataType: "text",
async: true,
data: { csrfmiddlewaretoken: '{{ csrf_token }}' },
success: function (json) {
$('#drugName').html(json.drugInfo);
// $('.ajaxProgress').hide();
}
})
}
views.py:
def drugsanddoses(request):
drugIdentifier = request.POST.get('drugID')
print(drugIdentifier)
drugInfo = RiskCalculator.objects.values('drug_name', 'l_dose', 'h_dose', 'risk', 'pubmed_id', 'updated')
response_data = {}
try:
response_data['drugInfo'] = str(drugInfo)
except:
response_data['result'] = 'No details found'
response_data['message'] = 'There is currently no information in the database for this drug.'
return HttpResponse(json.dumps(response_data), content_type="application/json")
You're making two Ajax requests; one a POST, where the ID is present, and one a GET, where the ID is absent so it prints None. I don't really understand why you're making two requests, but that is what you are doing.

Categories