Я хотел бы реализовать такую логику:
Сейчас у меня есть три кнопки: "Плюс" - увеличивает количество на 1 и меняет значение на странице. "Минус" - уменьшает количество на 1 и меняет значение на странице. «Подтвердить» — кнопка, которая отправляет запрос с текущим параметром количества на контроллер Spring Boot и изменяет количество на стороне сервера. Я бы предпочел избежать этой кнопки, потому что она добавляет сложности.
Есть ли удобный способ избавиться от кнопки подтверждения? Единственный известный мне способ сделать это — отправить запрос контроллеру при каждом нажатии кнопки «Плюс» или «Минус». Но похоже, что такой подход будет неэффективен.
$(document).ready(function () {
//include csrf for every ajax call
$(function () {
let token = $("meta[name='_csrf']").attr("content");
let header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function (event, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
$(".plusForm").submit(function (event) {
event.preventDefault();
let $prodCount = $(this).parent().parent().parent().find(".prodCount span");
let currentQuantity = parseInt($prodCount.text());
$prodCount.text(++currentQuantity);
});
$(".minusForm").submit(function (event) {
event.preventDefault();
let $prodCount = $(this).parent().parent().parent().find(".prodCount span");
let currentQuantity = parseInt($prodCount.text());
$prodCount.text(--currentQuantity);
});
$(".changedQuantityForm").submit(function (event) {
event.preventDefault();
let $prodCount = $(this).parent().parent().parent().find(".prodCount span");
let quantity = parseInt($prodCount.text());
let productId = $(this).parent().parent().parent().parent().find(
'.product-id').val();
changeQuantityAjax(productId, quantity);
});
function changeQuantityAjax(id, quantity) {
console.info("quantity changed on server side");
/* $.ajax({
type: "PUT",
contentType: "application/json",
url: "/rest/cart/" + id + "?quantity = " + quantity,
data: {
"quantity": quantity
},
success: function () {
console.info('SUCCESS ' + id + ' ' + quantity);
// alert(name + ' was deleted')
},
error: function () {
console.info('ERROR ' + id + ' ' + quantity);
}
}); */
}
})
<link href = "https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css"
rel = "stylesheet" media = "screen"/>
<script src = "https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src = "https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<link rel = "stylesheet" href = "https://use.fontawesome.com/releases/v5.5.0/css/all.css">
<div class = "row justify-content-center">
<div class = "col mb-4 prodItem">
<div class = "card border-primary" style = "height: 34rem; width: 26rem;">
<div class = "view overlay">
<img class = "card-img-top img-fluid"
src = "https://cdn.pixabay.com/photo/2018/10/05/23/24/chicken-3727097_1280.jpg"
style = "height : 18rem;" alt = "Card image cap">
<div class = "mask rgba-white-slight"></div>
</div>
<div class = "card-body">
<h3><span>Chicken</span></h3>
<div class = "float-right">
<h2 class = "card-title"><span>1000</span> $</h2>
</div>
<br>
<br>
<br>
<div class = "form-control">
<div class = "row prodCount" style = "margin: auto; font-size: 17px">
<p> In cart :  </p>
<span>0</span>
<div class = "row float-right" style = "margin: auto">
<form class = "plusForm">
<button type = "submit" class = "btn-sm">
<i class = "fas fa-plus-circle fa-w-16 fa-3x text-danger"></i>
</button>
</form>
<form class = "minusForm">
<button type = "submit" class = "btn-sm">
<i class = "fa fa-minus-circle fa-w-16 fa-3x" aria-hidden = "true"></i>
</button>
</form>
<form class = "changedQuantityForm">
<button type = "submit" class = "btn-sm">
<i class = "fas fa-check fa-w-16 fa-3x text-success"></i>
</button>
</form>
</div>
</div>
</div>
<br>
</div> <!-- card-body -->
</div> <!-- card -->
</div>
ПК: Кажется, мой вопрос связан с этой темой (https://stackoverflow.com/a/7762539/14308420). Но я не уверен, следует ли мне применять это в моем случае и как это сделать.
Я извлек логику кнопки отправки для работы updateQuantityOnServer(button)
. И после добавления этой строки:
changedQuantityTimeout = setTimeout(updateQuantityOnServer(this), 1000);
Я получил предупреждение:
Тип аргумента void нельзя присвоить типу параметра TimerHandler. Тип void нельзя присвоить типу string | Тип функции void не может быть назначен типу функции.
Как я понимаю, это вызвано тем, что я посылаю кнопку в качестве параметра. Но я использую эту кнопку для получения параметров...
Да, я извлек логику кнопки отправки для функции updateQuantityOnServer (кнопка). И после добавления этой строки: changeQuantityTimeout = setTimeout(updateQuantityOnServer(this), 1000); Я получил предупреждение: Тип аргумента void нельзя присвоить типу параметра TimerHandler Тип void нельзя присвоить типу string | Тип функции void не может быть назначен типу функции. Насколько я понимаю, это вызвано тем, что я отправляю кнопку в качестве параметра. Но я использую эту кнопку для получения параметров, поэтому решил спросить.
«Код, который вы разместили, не подходит». Можете ли вы объяснить, что вы имеете в виду? Мой код на jsfiddle не работает?
Ваша рабочий пример работает. Но 1) это весь код, а не только соответствующий. 2) В этой скрипке не заметно никаких попыток. 3)Скрипки и любые внешние ссылки могут измениться или исчезнуть. Вот почему соответствующий код должен быть размещен в вашем вопросе.
Я могу отредактировать ваш вопрос, если хотите... Чтобы помочь. И вы лучше поймете, что такое хороший вопрос.
Я отредактировал ваш вопрос, как и должно быть. Взгляните на изменения.
Посмотрите на функцию changeQuantityAjax
для реализации clearTimeout и setTimeout вместе, делая «минимальную» задержку в 2 секунды после последнего действия пользователя.
При каждом нажатии кнопки this
передавалось в функцию getIdandQuantity
.
Это не сильно меняет логику, но обратите внимание на .parents()
вместо parent().parent().parent()
.
$(document).ready(function() {
//include csrf for every ajax call
$(function() {
let token = $("meta[name='_csrf']").attr("content");
let header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(event, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
$(".plusForm").submit(function(event) {
event.preventDefault();
let $prodCount = $(this).parents(".prodCount").find("span");
let currentQuantity = parseInt($prodCount.text());
$prodCount.text(++currentQuantity);
getIdandQuantity(this);
});
$(".minusForm").submit(function(event) {
event.preventDefault();
let $prodCount = $(this).parents(".prodCount").find("span");
let currentQuantity = parseInt($prodCount.text());
$prodCount.text(--currentQuantity);
getIdandQuantity(this);
});
// That is the function to retreive the id and quantity from the clicked button
function getIdandQuantity(btn) {
let $parent = $(btn).parents(".prodCount");
let quantity = parseInt($parent.find("span").text());
let productId = $parent.find('.product-id').val();
changeQuantityAjax(productId, quantity);
}
// A variable to store the refence to the pending setTimeout
let ajaxTimeout
function changeQuantityAjax(id, quantity) {
// Clear any existing setTimeout
clearTimeout(ajaxTimeout)
// Set a 2 seconds timeout
ajaxTimeout = setTimeout(function() {
console.info("quantity changed on server side");
/* $.ajax({...}) */
}, 2000)
}
})
<link href = "https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel = "stylesheet" media = "screen" />
<script src = "https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src = "https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<link rel = "stylesheet" href = "https://use.fontawesome.com/releases/v5.5.0/css/all.css">
<div class = "row justify-content-center">
<div class = "col mb-4 prodItem">
<div class = "card border-primary" style = "height: 34rem; width: 26rem;">
<div class = "view overlay">
<img class = "card-img-top img-fluid" src = "https://cdn.pixabay.com/photo/2018/10/05/23/24/chicken-3727097_1280.jpg" style = "height : 18rem;" alt = "Card image cap">
<div class = "mask rgba-white-slight"></div>
</div>
<div class = "card-body">
<h3><span>Chicken</span></h3>
<div class = "float-right">
<h2 class = "card-title"><span>1000</span> $</h2>
</div>
<br>
<br>
<br>
<div class = "form-control">
<div class = "row prodCount" style = "margin: auto; font-size: 17px">
<p> In cart :  </p>
<span>0</span>
<div class = "row float-right" style = "margin: auto">
<form class = "plusForm">
<button type = "submit" class = "btn-sm">
<i class = "fas fa-plus-circle fa-w-16 fa-3x text-danger"></i>
</button>
</form>
<form class = "minusForm">
<button type = "submit" class = "btn-sm">
<i class = "fa fa-minus-circle fa-w-16 fa-3x" aria-hidden = "true"></i>
</button>
</form>
</div>
</div>
</div>
<br>
</div>
<!-- card-body -->
</div>
<!-- card -->
</div>
Дополнительно! Вы можете легко объединить 4 функции выше (2 обработчика кликов, getIdandQuantity
и changeQuantityAjax
) в один обработчик кликов.
$(document).ready(function() {
//include csrf for every ajax call
$(function() {
let token = $("meta[name='_csrf']").attr("content");
let header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(event, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
// A variable to store the refence to the pending setTimeout
let ajaxTimeout
$(".plusForm, .minusForm").submit(function(event) {
event.preventDefault();
// Get the elements needed, the product is and the quantity shown
let $parent = $(this).parents(".prodCount");
let id = $parent.find('.product-id').val();
let $prodCount = $parent.find("span")
let currentQuantity = parseInt($prodCount.text());
// Increment OR decrement the quantity
let quantity = ($(this).hasClass("plusForm")) ? ++currentQuantity : --currentQuantity
// Update the shown quantity
$prodCount.text(quantity)
// Clear any existing setTimeout
clearTimeout(ajaxTimeout)
// Set a 2 seconds timeout
ajaxTimeout = setTimeout(function() {
console.info("quantity changed on server side");
/* $.ajax({...}) */
}, 2000)
});
})
<link href = "https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel = "stylesheet" media = "screen" />
<script src = "https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src = "https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<link rel = "stylesheet" href = "https://use.fontawesome.com/releases/v5.5.0/css/all.css">
<div class = "row justify-content-center">
<div class = "col mb-4 prodItem">
<div class = "card border-primary" style = "height: 34rem; width: 26rem;">
<div class = "view overlay">
<img class = "card-img-top img-fluid" src = "https://cdn.pixabay.com/photo/2018/10/05/23/24/chicken-3727097_1280.jpg" style = "height : 18rem;" alt = "Card image cap">
<div class = "mask rgba-white-slight"></div>
</div>
<div class = "card-body">
<h3><span>Chicken</span></h3>
<div class = "float-right">
<h2 class = "card-title"><span>1000</span> $</h2>
</div>
<br>
<br>
<br>
<div class = "form-control">
<div class = "row prodCount" style = "margin: auto; font-size: 17px">
<p> In cart :  </p>
<span>0</span>
<div class = "row float-right" style = "margin: auto">
<form class = "plusForm">
<button type = "submit" class = "btn-sm">
<i class = "fas fa-plus-circle fa-w-16 fa-3x text-danger"></i>
</button>
</form>
<form class = "minusForm">
<button type = "submit" class = "btn-sm">
<i class = "fa fa-minus-circle fa-w-16 fa-3x" aria-hidden = "true"></i>
</button>
</form>
</div>
</div>
</div>
<br>
</div>
<!-- card-body -->
</div>
<!-- card -->
</div>
But I'm not sure if I should apply it...
Да, вы должны. Попытался ли ты? - Код, который вы разместили, не подходит.