0
I followed a solution on how to get Django Like and Unlike button not to reload the page on click. The solution i found works but only with TEXT toggle (Like and Unlike) and i want an Icon Toggle (Like and Unlike Icon).
I am new to Django Backend and Ajax, i will be happy if someone can help on how to deal with this. Thanks in Advance.
$( document ).ready(function() {
$('.like-form').submit(function(e){
e.preventDefault()
const post_id = $(this).attr('id')
const likeText = $(`.like-btn${post_id}`).text()
const trim = $.trim(likeText)
const url = $(this).attr('action')
let res;
const likes = $(`.like-count${post_id}`).text()
const trimCount = parseInt(likes)
$.ajax({
type: 'POST',
url: url,
data: {
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
'post_id':post_id,
},
success: function(response) {
if(trim === 'Unlike') {
$(`.like-btn${post_id}`).text('Like')
res = trimCount - 1
} else {
$(`.like-btn${post_id}`).text('Unlike')
res = trimCount + 1
}
$(`.like-count${post_id}`).text(res)
},
error: function(response) {
console.log('error', response)
}
})
});
});
<!-- Like Button -->
<li class="list-inline-item">
<form action="{% url 'posts:like-post-view' %}" method="POST" class='like-form' id='{{obj.id}}'>
{% csrf_token %}
<input type="hidden" name="post_id" value={{obj.id}}>
<button type="submit" class="btn btn-link g-color-gray-dark-v5 g-color-red--hover text-red p-0 border-0 btn-outline-light like-btn{{obj.id}}">
{% if user not in obj.liked.all %}
Like
<i class="align-middle mr-1 icon-heart u-line-icon-pro g-font-size-25"></i>
{% else %}
Unlike
<i class="align-middle mr-1 icon-like u-line-icon-pro g-font-size-25"></i>
{% endif %}
</button>
<span class="g-color-gray-dark-v5 g-font-size-15 like-count{{obj.id}}"> {{obj.num_likes}}</span>
</form>
</li>
<!-- End Like Button -->
You can append icons as well inside your success function with text . Also , put like and unlike inside span so that it would be easy to change value .
Demo Code :
$('.like-form').submit(function(e) {
e.preventDefault()
const post_id = $(this).attr('id')
const likeText = $(".like-btn"+post_id).find("i").hasClass("fa-heart-o") ? "Unlike":"Like"//check for class and if true then set value as unlike or like..
const trim = $.trim(likeText)
const url = $(this).attr('action')
let res;
const likes = $(`.like-count${post_id}`).text()
const trimCount = parseInt(likes)
/* $.ajax({
type: 'POST',
url: url,
data: {
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
'post_id': post_id,
},
success: function(response) {*/
if (trim === 'Unlike') {
//use .html to add htmls codes
$(`.like-btn${post_id}`).html('<i class="fa fa-heart" aria-hidden="true"></i>')
res = trimCount - 1
} else {
$(`.like-btn${post_id}`).html('<i class="fa fa-heart-o" aria-hidden="true"></i>')
res = trimCount + 1
}
$(`.like-count${post_id}`).text(res)
/* },
error: function(response) {
console.log('error', response)
}
})*/
});
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="{% url 'posts:like-post-view' %}" method="POST" class='like-form' id='1'>
<input type="hidden" name="post_id" value=1>
<button type="submit" class="btn btn-link g-color-gray-dark-v5 g-color-red--hover text-red p-0 border-0 btn-outline-light like-btn1">
<!--put texxt inside span-->
<i class="fa fa-heart" aria-hidden="true"></i>
</button>
<span class="g-color-gray-dark-v5 g-font-size-15 like-count1">12</span>
</form>
<form action="{% url 'posts:like-post-view' %}" method="POST" class='like-form' id='2'>
<input type="hidden" name="post_id" value=2>
<button type="submit" class="btn btn-link g-color-gray-dark-v5 g-color-red--hover text-red p-0 border-0 btn-outline-light like-btn2">
<i class="fa fa-heart-o" aria-hidden="true"></i>
</button>
<span class="g-color-gray-dark-v5 g-font-size-15 like-count2">5</span>
</form>
Related
I am trying to hide a modal after submitting a form. I am using bootstrap 5, vue 2 and django 3.2. I am a beginner in javascript and vue.
I can asynchronously submit the form with fetch and clear the fields, but I can't close the modal.
I report part of my code (bootstrap and vue only) which unfortunately does not provide a minimum reproducible example, but I hope it is sufficient.
The html template is:
<div style="margin-right: 230px" id="app">
<h4 style="text-align:left;float:left;">User Managment</h4>
<a
href="#"
data-bs-toggle="modal"
data-bs-target="#add_userModal"
class="btn btn-sm btn-outline-primary px-4"
style="text-align:right; float:right;">
Add
</a>
<hr style="clear:both; border-top: 1px solid grey;"/>
<table class="table" id="userTable">
<thead>
<tr>
<th class="col-md-4">First name</th>
<th class="col-md-8">Last name</th>
</tr>
</thead>
<tbody>
<tr v-for="userdb in usersdb">
<td>{% verbatim %}{{ userdb.first_name }}{% endverbatim %}</td>
<td>{% verbatim %}{{ userdb.last_name }}{% endverbatim %}</td>
</tr>
</tbody>
</table>
<div class="modal fade" id="add_userModal" tabindex="-1" aria-labelledby="add_userModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Utente</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form #submit.prevent="createUserdb">
<div class="modal-body">
<div class="form-group mb-3">
<label>First name*</label>
<input
type="text"
class="form-control"
id="first_name"
v-model="userdb.first_name"
required>
</div>
<div class="form-group mb-3">
<label>Last name*</label>
<input
type="text"
class="form-control"
id="last_name"
v-model="userdb.last_name"
required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-sm btn-outline-primary">Add</button>
</div>
</form>
</div>
</div>
</div>
</div>
The javascript code is
var app = new Vue({
el: '#app',
data: {
csrf: null,
userdb: {
first_name: '',
last_name: '',
full_name: ''},
usersdb: []
},
methods: {
async sendRequest(url, method, data) {
var myHeaders = new Headers({
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
})
if (method !== 'get') {
myHeaders.set('X-CSRFToken', await this.getCsrfToken())
};
var response = await fetch(url, {
method: method,
headers: myHeaders,
body: data
});
return response
},
async getCsrfToken() {
if (this.csrf === null) {
var response = await this.sendRequest(mainUrl + 'csrf', 'get')
var data = await response.json();
this.csrf = data.csrf_token;
};
return this.csrf;
},
async getUserdb() {
var response = await this.sendRequest(mainUrl, 'get');
this.usersdb = await response.json();
},
async createUserdb() {
await this.getUserdb();
await this.sendRequest(mainUrl, 'post', JSON.stringify(this.userdb));
this.userdb.first_name = '';
this.userdb.last_name = '';
await this.getUserdb();
}
},
async created() {
await this.getUserdb();
}
})
I made many attempts to add code in createUserdb, but without success. For example
document.getElementById("add_userModal").hide();
How can I hide the modal after submitting the form?
Any help is truly appreciated
You'll want to entirely manage the Bootstrap modal instance in the Vue app...
1 - First, add a new data var for the modal..
data: {
csrf: null,
userdb: {
first_name: '',
last_name: '',
full_name: ''},
usersdb: [],
myModal: null
},
2 - And a new method (ie: showModal()) to get an instance of the Bootstrap.modal and show it...
showModal(){
this.myModal = new bootstrap.Modal(document.getElementById('add_userModal'), {})
this.myModal.show()
},
3 - Bind the new method to #click handler to show the modal (instead of using data-bs attributes)...
<a
#click="showModal()"
class="btn btn-sm btn-outline-primary px-4"
style="text-align:right; float:right;">
Add
</a>
4 - Finally, call the hide() method after the async processing...
async createUserdb() {
await this.getUserdb();
await this.sendRequest(mainUrl, 'post', JSON.stringify(this.userdb));
this.userdb.first_name = '';
this.userdb.last_name = '';
this.myModal.hide()
}
Demo
<script>
$(document).ready(function() {
$("button").on('click', function(argument) {
$("button").attr('id', 'addtocart');
var product_id = $("#product_id").val();
if (product_id!="") {
$.ajax({
type : "POST",
url : "manage-cart.php",
data : 'product_id='+product_id,
success : function (response) {
// action to be performed if successful
$('#addtocart').removeAttr('id');
}
})
}
})
});
</script>
<div class="buttons">
<button class="" type="submit" >
<i class="fa fa-shopping-cart"></i>Add to Cart</button>
</div>
<input type="hidden" id="product_id" value ="5">
<div class="buttons">
<button class="" type="submit" >
<i class="fa fa-shopping-cart"></i>Add to Cart</button>
</div>
<input type="hidden" id="product_id" value ="6">
<div class="buttons">
<button class="" type="submit" >
<i class="fa fa-shopping-cart"></i>Add to Cart</button>
</div>
<input type="hidden" id="product_id" value ="7">
<div class="buttons">
<button type="submit" >
<i class="fa fa-shopping-cart"></i>Add to Cart</button>
</div>
<input type="hidden" id="product_id" value ="8">
this is the script and HTML code I'm working with. When the button is clicked the id is added to all the buttons and that's not the idea I want the id to be added to just the clicked button and removed after execution of the ajax script.
you need to use $(this)
$(document).ready(function() {
$("button").on('click', function(argument) {
var _t = $(this);
_t.attr('id', 'addtocart');
var product_id = $("#product_id").val();
if (product_id!="") {
$.ajax({
type : "POST",
url : "manage-cart.php",
data : 'product_id='+product_id,
success : function (response) {
// action to be performed if successful
_t.removeAttr('id');
}
})
}
})
});
</script>
<form id="review" method="post">
{% csrf_token %}
<button type="submit" id="sbtn" class="btn btn-primary btn-icon-split btn-lg" value="{{ Asin }}" >
<span class="icon text-white-50">
<i class="fas fa-poll-h"></i>
</span>
<span class="text">Fetch Reviews</span>
</button>
</form>
This is my html form on a Django rendered page
<script type="text/javascript">
$(document).on('submit','#review'.function(e){
e.preventDefault();
e.stopPropagation();
$.ajax({
type:'POST',
URL:'/reviews/',
data:{
asin:$('#sbtn').val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
},
beforeSend:function() {
$('#loader').removeClass('hidden');
},
complete : function() {
$('#loader').addClass('');
}});
return false;
});
This is the ajax function on the page.
The problem is...the current page is the result of a form on a previous page so as soon as the form-submit event is invoked the page refreshes and data on the page is lost. I tried both
e.preventDefault()
and
e.stopPropagation()
but that doesn't help. I'd like to know if you have some approach or a workaround..Thank you!
To make this work change this part of code:
<button type="submit" id="sbtn" class="btn btn-primary btn-icon-split btn-lg" value="{{ Asin }}" >
Like that:
<button type="button" id="sbtn" class="btn btn-primary btn-icon-split btn-lg" value="{{ Asin }}" >
<button type="submit" id="submit_sbtn" class="d-none">
The submit button is not necessary.
Then change your script to send an ajax request to $('#sbtn') click event. And then submit your form.
$(document).on('submit','#review', function() {
$('#loader').removeClass('hidden');
$.ajax({
method: "POST",
type: "POST",
url: "/reviews/",
data: {
asin:$('#sbtn').val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
}
}).done( function( msg ) {
$('#loader').addClass('');
console.log(msg)
}).fail( function(error) {
console.log(error)
})
return false;
})
I'm trying to update a variable in an html page after it has been updated using an AJAX call:
{% for q in questions %}
{% if qdelete == forloop.counter %}
<div align= Center>
<button type="submit" class="btn btn-primary btn-small" id="qyesbtn" name="qyesbtn" value="qyesbtn_{{q.id}}">Yes »</button>
</div>
<div align= Center>
<button type="submit" class="btn btn-primary btn-small" id="qnobtn" name="qnobtn" value="qnobtn">No »</button>
</div>
{% else %}
<button type="button" id="qbtn" class="btn btn-primary btn-large" name="qid" value="{{forloop.counter}}" onclick="SetDeleteNum({{forloop.counter}})">Delete »</button>
{% endif %}
{% endfor %}
<script>
function SetDeleteNum(d) {
var num = -1
num = d
console.log('num: '+num)
var page = $(this)
$.ajax({
type: "POST",
url: "{% url 'home' %}",
data: {
'csrfmiddlewaretoken': $('input[name="csrfmiddlewaretoken"]').val(),
'qid': num
},
dataType: 'json',
success: function (data) {
console.log('aa'+JSON.stringify(data))
page.html(data);
},
error: function(e){
console.log('err: '+JSON.stringify(e))
}
});
}
</script>
The value qdelete should be updated to 'num' after the AJAX call but it is still as before although I can see from the logs that the qdelete has the new value assigned but it simply not displayed in the page. I also tried to put the new 'data' in the new html using the line 'page.html(data);' but no luck. Any idea?
I found the solution simply I put ids on all the buttons:
<div align= Center id="qbtn_{{forloop.counter}}" style="display:block">
<button type="button" class="btn btn-primary btn-large" name="qid" value="{{forloop.counter}}" onclick="SetDeleteNum({{forloop.counter}})">Delete »</button>
</div>
<div align= Center id="ybtn_{{forloop.counter}}" style="display:none">
<button type="submit" class="btn btn-primary btn-small" id="qyesbtn" name="qyesbtn" value="qyesbtn_{{q.id}}">Yes »</button>
</div>
<div align= Center id="nbtn_{{forloop.counter}}" style="display:none">
<button type="button" class="btn btn-primary btn-small" id="qnobtn" name="qnobtn" value="qnobtn" onclick="SetDeleteNum({{forloop.counter}})">No »</button>
</div>
and then I show/hide the buttons according to the counter value:
function SetDeleteNum(d) {
var num = -1
num = d
console.log('num: '+num) //code to refresh the page
//var page_y = $( document ).scrollTop();
//window.location.href = window.location.href + '?page_y=' + page_y;
//var div = $(this).getElementById("qbtn_"+num.toString())
console.log('dd: '+'-')
div_q = document.getElementById("qbtn_"+num.toString())
div_y = document.getElementById("ybtn_"+num.toString())
div_n = document.getElementById("nbtn_"+num.toString())
//div.disabled = true
if(div_q.style.display == 'block'){
div_y .style.display = 'block';
div_n .style.display = 'block';
div_q.style.display = 'none';
}
else{
div_q.style.display = 'block';
div_n .style.display = 'none';
div_y .style.display = 'none';
}
}
hope it helps to others
i have the following html/php code (php tag ommited)
$user = array(
'name' => Null,
'address' => Null
);
<div id="user">
<a href="#" id="cust_name" data-type="text"
data-pk="'.$user['ag_id'].'" title="Enter customer name">'.$user['name'].'</a>
<a href="#" id="cust_addr" data-type="text"
data-pk="'.$user['ag_id'].'" title="Enter customer address">'.$user['address'].'</a>
<div class="modal-footer">
<button type="button" class="btn btn-default" id="ResetButton">Reset</button>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="SaveButton"
data-dismiss="modal">Save changes</button>
</div>
</div>
could you please complete my resetbutton script, the purpose is to assign null to cust_name and cust_addr after the click.. here's the script
<script>
$.fn.editable.defaults.mode = 'inline';
$(function(){
$('#user a').editable({
url: 'post.php'
});
});
$("#SaveButton").click(function() {
$.ajax({
url: 'db.php',
type: 'POST',
data: {}
});
});
$('#ResetButton').click(function() {
// $('#cust_name').editable('setValue', null); // did not worked
// didn't worked even i added class="myeditable" in my <a> tag
/*
$('.myeditable').editable('setValue', null)
.editable('option', 'pk', null)
.removeClass('editable-unsaved');
*/
});
</script>
This seemed to work.
http://jsfiddle.net/U33kT/
I'm not sure the difference, except that I chose all editables (JS line 6):
$('#user a').editable('setValue', null);
But, I tried with single items:
$('#cust_name').editable('setValue', null);
and it seemed to work as well.
Hope this helps.