Execute Ajax request Only Once - javascript

$('#addToCart').click(function () {
let csrf = $("input[name=csrfmiddlewaretoken]").val();
let trTable = $(this).parents('div')[1];
let customPrice = $($(trTable).children('div')[0]).find('#customPrice').val();
let quantity = $($(trTable).children('div')[1]).find('#quantity').val();
let productID = $('#addToCart').attr('data-product-id');
$.ajax({
url: "{% url 'cart:cart_add' %}",
method: 'POST',
dataType: 'json',
data: {
'csrfmiddlewaretoken': csrf,
productID: productID,
quantity: quantity,
customPrice: customPrice
},
success: function (data) {
$('#exampleModal').modal('hide');
let cart = $('#cart').children('tr');
let id = null;
jTotal = $('#total')
let trTable = $(this).parents('td');
let quantityField = '';
for (let i = 0; i < cart.length; i++) {
let tds = $(cart[i]).children('td')
let td = $(cart[i]).children('td')[tds.length - 1];
let ID = $(td).children('button').attr('data-product-id');
if (ID == data.id) {
quantityField = $(cart[i]).children('td')[1];
totalPriceField = $(cart[i]).children('td')[2];
id = ID;
}
}
if (data.id == id) {
$(quantityField).text(data.quantity);
$(totalPriceField).text(data.total);
jTotal.find('.total').find('.num').html(data.totalPrice);
} else {
$('#cart').append(
`<tr>
<td class="jsgrid-cell productName">${data.name}</td>
<td class="jsgrid-cell productQuantity" >${data.quantity}</td>
<td class="jsgrid-cell totalPrice">${data.total}</td>
<td class="productID"">
<button type="button" data-product-id="${data.id}" class="btn btn-sm btn-danger remove mgt"><i class="fa fa-trash"></i></button>
</td>
</tr>
`);
jTotal.find('.total').find('.num').html(data.totalPrice);
}
$('.remove').one("click", function() {
const result = confirm('Вы точно хотите удалить этот товар из корзины?');
if (result) {
let csrf = $("input[name=csrfmiddlewaretoken]").val();
let trTable = $(this).parents('td');
$.ajax({
url: "{% url "cart:cart_remove" %}",
method: 'POST',
dataType: 'json',
data: {
'csrfmiddlewaretoken': csrf,
productID: data.id,
},
success: function (data) {
sellPrice = $(trTable.parents('tr').find('.totalPrice')).html();
absoluteTotalPrice = jTotal.find('.total').find('.num').html();
totalCost = Number(absoluteTotalPrice) - Number(sellPrice);
jTotal.find('.total').find('.num').html(totalCost);
trTable.parents('tr').remove();
}
});
}
});
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Button .remove should work only once, how can i make this happen? It spawns multiple times. For example if click that addToCart button 2 times, this remove is spawning to times in a row, i need it so that it will just once.
My problem is that i have products and i add them via this button $('#addToCart').click(function () using ajax, and i have cart that is storing products. This button $('.remove').click(function () should be added to each product, but this button is in #addToCart button, and when multiple products is added, $('remove") button is working multiple times too.Sorry for bad english

You can simply use jQuery one to call your ajax request once per element.
Run snippet below to see it work only once.
$(".click-me").one("click", function() {
console.log("clicked");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="click-me">Remove</button>

You can use on and off to avoid a double click.
$(".remove").on("click", function() {
$(".remove").off("click");
console.log("clicked");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="remove">Remove</button>

You could use offto remove the event listener after your onclick event
$('.remove').click(
function () {$('.remove').off("click")
//...

Related

Changing Button Text based on the button clicked - not all buttons

I am trying to change the text of the button clicked, using beforeSend and Complete in an ajax function, changing the text from Add to Cart > Adding... > Added to Cart, but the text is changed in all buttons, not sure how to target the button clicked.
HTML - the button text is wrapped in a space with data attributes
<span class="js-btn-cta" data-addbtn="{{ btn_txt }}" data-soldout="{{ btn_txt_soldout }}" data-offerbtn="{{ btn_txt_selling }}" data-adding-cart="{{ btn_adding }}" data-added-cart="{{ btn_added }}">
JS - I am then changing the text before the request is sent and once complete using the following methods;
//START AJAX API ADD TO CART FUNCTION
let miniCartContentsSelector = '.js-mini-cart-contents';
let addingCartBtn = $('.add-to-cart-button');
let addingCartText = $('.js-btn-cta');
let ajaxify = {
onAddToCart: function(event){
event.preventDefault();
$.ajax({
type: 'POST',
url: '/cart/add.js',
data: $(this).serialize(),
dataType: 'json',
beforeSend: function(e) {
//Update btn text on product and collection pages
dataAddingCart = addingCartText.attr('data-adding-cart'),
addingCartText.text(dataAddingCart);
},
complete: function(e) {
//Update btn text on product and collection pages
dataAddedCart = addingCartText.attr('data-added-cart'),
addingCartText.text(dataAddedCart);
},
success: function(){
ajaxify.onCartUpdated();
currencyPicker.setCurrencyText();
},
error: ajaxify.onError
});
shippingBar.update();
},
onCartUpdated: function() {
$.ajax({
type: 'GET',
url: '/cart',
context: document.body,
success: function(context){
let
$dataCartContents = $(context).find('.js-cart-page-contents'),
$dataCartContentsPrice = $(context).find('.js-total'),
dataCartHtml = $dataCartContents.html(),
dataCartItemCount = $dataCartContents.attr('data-cart-item-count'),
dataCartItemTotal = $dataCartContentsPrice.attr('data-cart-item-total'),
$miniCartContents = $(miniCartContentsSelector),
$cartItemCount = $('.js-cart-item-count'),
$closeIcon = $('.js-close-cart'),
$cartItemTotal = $('.js-cart-item-total');
$cartItemCount.text(dataCartItemCount);
$cartItemTotal.html('<span class="money">' + dataCartItemTotal + '</span>');
$miniCartContents.html(dataCartHtml);
//change currency in cart when changed
currencyPicker.setCurrencyText();
Currency.convertAll(shopCurrency, Currency.currentCurrency);
if (parseInt(dataCartItemCount) > 0){
ajaxify.openCart();
$('.js-minus').prop("disabled", true);
}
else {
ajaxify.closeCart();
}
//close the cart drawer when clicking on x in cart header
function closeClick(event){
$('body').removeClass('show-sidebar');
console.log('close icon btn clicked');
}
//end close the cart drawer when clicking on x in cart header
//call the closeClick function
$('.js-close-cart').click(closeClick);
//end call the closeClick function
}
});
//reset pdp qty value to 1 once add to cart has been clicked
$(".js-quantity-field-pdp").val("1");
shippingBar.update();
ajaxify.closeModal();
},
onError: function(XMLHttpRequest, textStatus){
let data = XMLHttpRequest.responseJSON;
alert(data.status + ' - ' + data.message + ': ' + data.description);
},
openCart: function(){
let isInCartPage = window.location.href.indexOf('/cart') === -1;
if(isInCartPage) {
$('body').addClass('show-sidebar');
}
},
closeCart: function(){
$('body').removeClass('show-sidebar');
},
closeModal: function(){
$('.modal').modal('hide');
$('.modal-backdrop').modal('hide');
},
onCartButtonClick: function(event){
event.preventDefault();
//If the body has a class of show-sidebar, return TRUE.
let isCartOpen = $('body').hasClass('show-sidebar');
let isInCart = window.location.href.indexOf('/cart') === -1;
if(!isInCart) {
if(!isCartOpen) {
ajaxify.openCart();
}
else {
ajaxify.closeCart();
}
}
},
init: function(){
$(document).on('submit', addToCartFormSelector, ajaxify.onAddToCart);
$(document).on('click', '.js-menu-toggle active', ajaxify.onCartButtonClick);
$(document).on('click', '#mini-cart .js-keep-shopping', ajaxify.onCartButtonClick);
}
};
//initiate the function
ajaxify.init();
The problem is it changes button text for other buttons not clicked.
Thanks
You get all button with class "js-btn-cta" and you change the text attribute to all button with this class. Not only the action button.
Inside onAddToCart, you have to get the clicked button.
onAddToCart: function(event){
var clickedButton = $(this);
event.preventDefault();
$.ajax({
type: 'POST',
url: '/cart/add.js',
data: $(this).serialize(),
dataType: 'json',
beforeSend: function(e) {
//Update btn text on product and collection pages
dataAddingCart = clickedButton.attr('data-adding-cart'),
clickedButton.text(dataAddingCart);
},
complete: function(e) {
//Update btn text on product and collection pages
dataAddedCart = clickedButton.attr('data-added-cart'),
clickedButton.text(dataAddedCart);
},

Save userId in sessionStorage giving error?

I want to store the variable "clients[i]._id" and send it to another page when I click the button in the for loop.I want to later use that id to get more specific information about that client on its seperate window.
Im getting an undefined error where clients is undefined. Also the console.log in the store(function) doesnt work. Can you find whats wrong?
let thisArray = [];
//let clientId = $('#clientId').val();
$.ajax({
method: 'GET',
url: '/auth/clientsGET',
dataType: 'json',
success: function(clients) {
thisArray = clients
buildTable(thisArray);
console.log(thisArray);
}
})
function buildTable(clients) {
let table = document.getElementById('tabelaClientesAdmin')
for (let i = 0; i < clients.length; i++) {
let row = `<tr>
<td>${clients[i]._id}</td>
<td>${clients[i].name}</td>
<td>${clients[i].admin}</td>
<td><button type="button" class="btn btn-primary" onclick="store()">Ver Cliente</button></td>
</tr>`
table.innerHTML += row
}
}
function store() {
console.log("Trying to get clientId....")
let clientId = clients._id;
sessionStorage.setItem("clientId", clientId);
location.href = "./ver_cliente";
}
I'll update straight away when information is needed.
You could pass the index like that:
onclick="store(${i})"
then retrieve it like that:
function store(index) {
const clientId = thisArray[index]._id;
sessionStorage.setItem("clientId", clientId);
}
Here is a slightly modified but working example of your page:
The most important part is probably:
let clientId=+ev.target.closest("tr").children[0].textContent;
where I navigate from the clicked button (ev.target) via the parent-<tr> to the first child (a <td>). There I read the textContent, convert it into an integer with the unary +-operator and store it in variable clientId.
I also introduced the global variable clients that could be used for further reference in the page. But currently this array not really used anywhere.
var clients
$.ajax({
method: 'GET',
url: 'https://jsonplaceholder.typicode.com/users',
dataType: 'json',
success: function(d) {
clients = d
buildTable(clients);
console.log(clients);
}
})
function buildTable(clients) {
let table = document.getElementById('tabelaClientesAdmin')
for (let i = 0; i < clients.length; i++) {
let row = `<tr>
<td>${clients[i].id}</td>
<td>${clients[i].name}</td>
<td>${clients[i].username}</td>
<td><button class="btn btn-primary">Ver Cliente</button></td>
</tr>`
table.innerHTML += row
}
}
document.body.onclick=function(ev) {
if (ev.target.tagName==="BUTTON") {
let clientId=+ev.target.closest("tr").children[0].textContent;
console.log("Trying to get clientId:",clientId);
// sessionStorage.setItem("clientId", clientId); // not in SO snippets
console.log("go to ./ver_cliente");
}}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="tabelaClientesAdmin"></table>

Ajax For HTML Generated From Javascript

I have html being generated from Javascript to create a list of items. I also need to call a Jquery Ajax call on each of those items but since it isn't in the html from the page ready I think that might be why the Ajax isn't called. When I click the submit button it tries to refresh the page so this shows that the prevent default isn't being run.
EDIT: spelling
What am i doing wrong here?
Javascript that generates HTML:
buildCollectionList()
function buildCollectionList(){
var url = 'http://localhost:8000/api/collection_items_list/'
fetch(url)
.then((resp) => resp.json())
.then(function(data){
for (var x in data){
var wrapper = document.getElementById(`collection_scroll${data[x].post}`)
var product = wrapper.getAttribute('name')
//console.log(product)
wrapper.innerHTML = ''
/*fetch(url)
.then((resp) => resp.json())
.then(function(data){
console.log('Data:', data)*/
var list = data
for (var i in list){
if ((list[i].saved == true) && (list[i].post == product)){
var item = `
<div class="collection_save_container">
<div class="collection_save_name">${list[i].parent_collection_name}</div>
<form class="collection_save_form" action="" method="POST" id="${list[i].collection}" name="${list[i].post}">
<button type="submit" class="collection_save_btn saved" id="save_btn ${list[i].collection} ${list[i].post}"><div class="saved_text ${list[i].collection}">Saved</div></button>
</form>
</div>
</div>
`
wrapper.innerHTML += item
} else if (list[i].post == product){
var item = `
<div class="collection_save_container">
<div class="collection_save_name">${list[i].parent_collection_name}</div>
<form class="collection_save_form" action="" method="POST" id="${list[i].collection}" name="${list[i].post}">
<button type="submit" class="collection_save_btn" id="save_btn ${list[i].collection} ${list[i].post}"><div class="saved_text ${list[i].collection}">Save</div></button>
</form>
</div>
</div>
`
wrapper.innerHTML += item
}
}
//})
}
})
}
Jquery Ajax:
$(document).ready(function() {
$('.collection_save_form').submit(function(e){
e.preventDefault()
//const url = $(this).attr('action')
const url = "{% url 'savepost' 0 1000 %}"
const post_id = $(this).attr('name')
const collection_id = $(this).attr('id')
const text = $(`.saved_text ${collection_id}`).text()
var saveElement = document.getElementById(`save_btn ${collection_id} ${post_id}`);
real_url = url.replace('0', post_id).replace('1000', collection_id);
$.ajax({
type: 'POST',
url: real_url,
data: {
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
'post_id': post_id,
'collection_id': collection_id,
},
success: function(response){
if (saveElement.classList.contains("saved")){
saveElement.classList.remove("saved")
$(`.saved_text${collection_id}`).text('Save')
} else if (!saveElement.classList.contains("saved")) {
saveElement.classList.add("saved")
$(`.saved_text${collection_id}`).text('Saved')
}
console.log(post_id)
},
error: function(response){
console.log('error', response)
}
})
})
});
for anyone with a similar problem: i solved this by putting an onclick event in the html that is generated by javascript

Ajax calls going multiple times

I have written a code in Javascript in which I have attached an input type submit to a form. On form submit the listener gets called.
The problem is that on when I click the button once, one ajax call occurs. When I click it again two calls occur while only one call should occur on each click. Similarly on clicking 3 times 3 calls occur and so on...(the calls get increasing). If I refresh the page then the number gets reset. I have tried everything but I had no luck. If anyone found out what is wrong here it would be awesome. Thanks in advance.
javascript code:
$('input.create-discounts-quotations').click(function () {
var discount_quotation_type = $('input.quotation-discount-type').val();
if (discount_quotation_type == "value") {
var total = $('input.discount-input-quotation').val();
var discounted_price = product_price - total;
$('#final_discounted_amount').val(discounted_price);
$("table.product-response-table tr").each(function () {
var row = $(this).index() + 1;
var td = $(this).find('td.quotation-response-discounts');
$(td).each(function () {
$(this).html(total);
});
});
$("table.product-response-table tr").each(function () {
var row = $(this).index() + 1;
var td = $(this).find('td.product_final_price_discounted');
$(td).each(function () {
$(this).html(discounted_price);
});
});
var form1 = $('form#quotation_discount_update_form');
form1.on("submit", function (e) {
var form_data1 = form1.serialize();
$.ajax({
type: 'POST',
url: form1.attr('action'),
data: form_data1,
dataType: "json",
success: function (data) {
$('.quotation-discount-status-update').empty();
$('.quotation-discount-status-update').append('<div class="alert alert-success">Discount Added</div>');
}
});
e.preventDefault();
});
}
if (discount_quotation_type == "percentage") {
var total = $('input.discount-input-quotation').val();
var temp_first = product_price;
var temp1 = total / 100;
var temp2 = temp1 * product_price;
var discounted_price = product_price - temp2;
$('#final_discounted_amount').val(discounted_price);
$("table.product-response-table tr").each(function () {
var row = $(this).index() + 1;
var td = $(this).find('td.quotation-response-discounts');
$(td).each(function () {
$(this).html(total);
});
});
$("table.product-response-table tr").each(function () {
var row = $(this).index() + 1;
var td = $(this).find('td.product_final_price_discounted');
$(td).each(function () {
$(this).html(discounted_price);
});
});
var form1 = $('form#quotation_discount_update_form');
form1.on("submit", function (e) {
var form_data1 = form1.serialize();
$.ajax({
type: 'POST',
url: form1.attr('action'),
data: form_data1,
dataType: "json",
success: function (data) {
$('.quotation-discount-status-update').empty();
$('.quotation-discount-status-update').append('<div class="alert alert-success">Discount Added</div>');
}
});
e.preventDefault();
});
}
if (discount_quotation_type == "not_selected") {
$('.quotation-discount-status-update').empty();
$('.quotation-discount-status-update').append('<div class="alert alert-danger">Discount Method Not Selected</div>');
return false;
}
// return false;
});
That happen because every time you click your code will reattach the submit event so it will be duplicated in every click.
You should never attach the events inside other events, please put the submit event outside of the click event and the code should work, example :
var form1 = $('form#quotation_discount_update_form');
form1.on("submit", function (e) {
var form_data1 = form1.serialize();
$.ajax({
type: 'POST',
url: form1.attr('action'),
data: form_data1,
dataType: "json",
success: function (data) {
$('.quotation-discount-status-update').empty();
$('.quotation-discount-status-update').append('<div class="alert alert-success">Discount Added</div>');
}
});
e.preventDefault();
});
Else you have to remove the event handler every time using .off(), like :
form1.off("submit").on("submit", function (e) {

Unable to retrieve data from html

As for my below code i am not able to get sectionID from tr, i need to get dynamic id of sectionID on each delete button click but it is always giving me null
Here is the Jquery Script :
<script>
$(function () {
$('.btnDelete').click(function () {
var sectionID = $(this).closest('tr').find('.sectionID');
$.ajax({
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: 'POST',
url: 'CheckSectionIDagainststudentID',
data: JSON.stringify({ sectionID: sectionID.html() }),
success: function (data) {
if (data == true) {
$.alert("Cannot delete | Students exsisting in this
Section!");
}
else if (data == false) {
var secCode = JSON.parse(this.data);
var code = sectionid['sectionid'];
window.location.href = "SectionDelete?Page=data&sectionid="
+ code;
}
},
failure: function (response) {
$('#result').html(response);
}
});
});
});
</script>
and here is Razor Page
#foreach (var item in Model)
{
<tr class="sectionID">
<td >
#Html.DisplayFor(modelItem => item.sectionID)
</td>
<td>
#Html.DisplayFor(modelItem => item.name)
</td>
<td class="secCode">
<button style="width:49.5%" ID="Button2" type="button" onclick="location.href='#Url.Action("SectionEdit", "Section",new { id = item.sectionID, name = item.name })'">Edit</button>
<button style="width:49.5%" ID="deletebtn" runat="server" type="button" onclick="location.href='#Url.Action("SectionDelete", "Section",new { id = item.sectionID, name = item.name })'">Delete</button>
<button class="btnDelete">Delete</button>
</td>
</tr>
}
This is Controller Which i need to pass data to
[HttpPost]
public ActionResult CheckSectionIDagainststudentID(string sectionID)
{
return Json(sectionID);
}
As per your question you are not able to get value from var sectionID = $(this).closest('tr').find('.sectionID');
therefore here is a way you can achieve your result
//Your Dynamic Button should look like this
//in value Bind your sectionID # MVC
<button class="btnDelete" value="5" onclick="AjaxDelete(this)">Delete</button>
//For Function
function AjaxDelete(values) {
//Write this in Ajax
//Fetch Value from attribute value
var sectionID = $(values).attr("value"); // you will get 5 as value
//Your Ajax Call with SectionId as Parameter
}
Edit :
as you have got value
U can split the value by below code
where string is your var of sectionID
if ((~string.indexOf('\n '))) {
string= string.split('\n ')[1].split('\n')[0];
}
Use string array :
[HttpPost]
public ActionResult CheckSectionIDagainststudentID(string[] sectionID)
{
return Json(sectionID);
}

Categories

Resources