pass controller with parameter in ajax symfony - javascript

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

Related

Get an ID just created without reloading the page

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

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("")

500 Internal error - error TokenMismatchException

Seem to be having problems with a TokenMismatchException on my Javascript button that are approving a comment. I have copied the code from a similar button system and changed it to match the requirements of this system. I am reusing the Session:Token variable, not sure if thats the issue?
Error: TokenMismatchException in verifycsrftoken.php line 68
Here is my code, any ideas on why i'm getting the mismatch error?
HTML:
#if(Auth::user())
#if($approval)
<a class="approval approved " data-id="{{$comments->id}}"><i class="fa fa-thumbs-up"></i></a>
#else
<a class="approval not-approved " data-id="{{$comments->id}}"><i class="fa fa-thumbs-up"></i></a>
#endif
#else
<a class="not-approved" href="{{route('login')}}"><i class="fa fa-thumbs-up"></i></a>
#endif
Javascript:
var token = '{{ Session::token() }}';
var urlApproval = '{{ route('approvals') }}';
$('.approval').on('click', function(event){
event.preventDefault();
var buttonToChange = $(this);
var $this = $(this);
$.ajax({
method: 'POST',
url: urlApproval,
data: { comment_id: $(event.target).data("id")}, _token: token })
.done(function() {
if(buttonToChange.hasClass('approved')) {
buttonToChange.addClass('not-approved');
buttonToChange.removeClass('approved');
}else {
buttonToChange.addClass('approved');
buttonToChange.removeClass('not-approved');
}
});
});
When using ajax in laravel, and using POST method you always need to provide the csrf token, so what you need to do is:
In your HTML:
<meta name="csrf-token" content="{{ csrf_token() }}">
Before call Ajax:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});

Change like status with jQuery on a flask app

I am working on a flask web app and I am trying to implement the like comment feature with jQuery so that the page does not have to reload when the like button is clicked. Below are my codes. Any help will be much appreciated.
route:
#main.route('/like-comment/<int:id>', methods=["GEt", "POST"])
def like_comment(id):
comment = Comment.query.filter_by(id=id).first()
if comment is None:
flash('This comment is invalid or has been deleted by the user')
return redirect(url_for('.home'))
current_user.like_comment(comment)
return jsonify({'result' : 'success', 'like_comment' : current_user.like_comment(comment)})
JavaScript:
$(document).ready(function() {
$('.like').on('click', function () {
var comment_id = $(this).attr('comment_id');
req = $.ajax({
url : '/like-comment',
type : 'POST',
data : {
like_comment : current_user.like_comment(comment),
id : comment_id
}
});
req.done(function (data) {
$('#like'+comment.id).text(data.like_comment);
});
});
});
HTML:
{% if not current_user.is_liking_comment(comment) %}
<button class="like btn btn-pill btn-warning btn-xs" comment_id="{{ comment.id }}">
<span class="icon icon-thumbs-up" id="like{{ comment.id }}"></span> Like
</button>
{% else %}
I don't use flask, but I see you're using an attribute "comment_id", is that a Flask thing? Otherwise, you should use "data-"...
In your HTML...
<button class="like btn btn-pill btn-warning btn-xs" data-comment_id="{{ comment.id }}">
And then in jQuery...
var comment_id = $(this).data('comment_id');
But I think the problem is that your returning JSON and you haven't indicated that to your $.ajax call...
$(document).ready(function() {
$('.like').on('click', function(event) {
event.preventDefault();
var comment_id = $(this).attr('comment_id');
$.ajax({
url : '/like-comment',
type : 'POST',
data : {
like_comment : current_user.like_comment(comment),
id : comment_id
},
dataType='json'
})
.done(function (data) {
$('#like'+comment.id).text(data.like_comment);
});
});
});
Or if you don't want to use Promises...
$(document).ready(function() {
$('.like').on('click', function(event) {
event.preventDefault();
var comment_id = $(this).attr('comment_id');
$.ajax({
url : '/like-comment',
type : 'POST',
data : {
like_comment : current_user.like_comment(comment),
id : comment_id
},
dataType='json',
success: function(data) {
$('#like'+comment.id).text(data.like_comment);
}
});
});
});
Let me know if it helps...
Try adding an action to your data object to call the function on the server. See below:
data: {
action: like_comment, //or the name of your function on the server
like_comment: current_user.like_comment(comment),
id: comment_id,
},

Switch form on submit - jQuery (Ajax)

I have a form to add item to favorites, and also to delete it.
Let's say this is form for adding and deleting:
#if($checkIfFavIsAdded == 0)
{!! Form::open(['id' => 'ajax-form-add', 'style' => 'float:right']) !!}
...
<button class="fa fa-star-o fa-2x" tool-tip-toggle="tooltip-demo" id="addFavbutton" title="Add item to favorites" style="color:#fd8809"></button>
{!! Form::close() !!}
#else
{!! Form::open(['id' => 'ajax-form-delete', 'style' => 'float:right']) !!}
...
<button class="fa fa-star-o fa-2x" tool-tip-toggle="tooltip-demo" id="addFavbutton" title="Delete item from favorites" style="color:grey"></button>
{!! Form::close() !!}
#endif
Here, I am checking if the item is added to favorites, and if so, the appropriate form should be shown.
It works on page reload, but how can I do this in Ajax?
I've tried to hide and show but without success. It just hides the form and don't display another one.
<script type="text/javascript">
$("#ajax-form-add").submit(function(event) {
event.preventDefault();
var form = $(this);
$.ajax({
type: "post",
url: "{{ url('addFavorites') }}",
dataType: "json",
data: form.serialize(),
success: function(data){
$("#ajax-form-add").hide();
$("#ajax-form-delete").show();
},
error: function(data){
swal("Error!", "error")
},
complete: function (data) {
}
});
});
</script>
<script type="text/javascript">
$("#ajax-form-delete").submit(function(event) {
event.preventDefault();
var form = $(this);
$.ajax({
type: "post",
url: "{{ url('deleteFavorites') }}",
dataType: "json",
data: form.serialize(),
success: function(data){
$("#ajax-form-delete").hide();
$("#ajax-form-show").show();
},
error: function(data){
swal("Error!", "Item is not available!", "error")
}
});
});
</script>
Blade templates are rendered server side, what you're trying to do is client side.
If you have that conditional in your blade template, the markup that gets rendered and sent to the browser will not include the other form.
You'll need to return the markup you want to display (IE the new form) in the ajax response.
For the second ajax you have written:
$("#ajax-form-show").show();
No, id with ajax-form-show is present. It should be:
$("#ajax-form-add").show();

Categories