Good day all, I've scratched my head for the past week trying to figure out this problem. Basically I'm using the Codeigniter 3 shopping cart library in my application. As it has the standard add to cart and remove products from cart, I tried to go one step ahead and tried to implement a quantity increment button with AJAX to make it even better.
So in my cart view, I have a minus button (to decrease the quantity by 1), followed by an input which displays the value quantity, and finally a plus button to increase the quantity by 1.
My problem is one button works flawlessly while the other just doesn't work. If I change my logic for that minus button to add 1 to the quantity instead of deducting 1 it still works as intended.
When I click the button (add_one_product), it fails to increment my quantity by 1, instead it refreshes my page and gives me these errors in console:
[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
[Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
[Violation] 'load' handler took 2308ms
I've read up on synchronous XHR, event listener errors with touchstart etc but I still can't figure out how to fix it.
Here I am sharing my code hoping someone with a better eye and more experience than me could help point out what is it that I am missing.
This is my controller:
function show_cart() {
$output = '';
$no = 0;
foreach ($this->cart->contents() as $items) {
$no++;
$output .='
<tr>
<th class="text-center" scope="row">
<div class="row">
<div class="col-lg-3 col-md-3 offset-lg-2 offset-md-2 p-0" style="background-image: url('.base_url($items['thumbnail']).'); background-size: cover;">
</div>
<div class="col-lg-6 col-md-6 p-3" style="text-align:left; margin-left:20px;font-size: 17px;font-family: ProximaNova;letter-spacing: 1px; text-transform: uppercase;">
'.$items['name'].'<br><br>
<button type="button" id="'.$items['rowid'].'" class="remove_cart btn btn-sm px-0" style="font-weight: 700; color: #892826;text-decoration: underline;font-size: 12px;font-family: ProximaNova;letter-spacing: 1px; background-color: white;">Remove</button>
</div>
</div>
</th>
<td class="font-weight-bold" style="padding-top: 40px;font-size: 17px;font-family: ProximaNova;letter-spacing: 1px;">RM '.number_format($items['price'],2).'</td>
<td>
<div class="input-group w-30" style="padding-top: 25px;">
<span class="input-group-btn">
<button type="button" id="'.$items['rowid'].'" class="remove_one_product btn btn-default btn-number" style="border: 1px solid #892826; color: white; background: #892826;"><span class="glyphicon glyphicon-minus"></span>
</button>
</span>
<input type="text" style="border: 1px solid #892826" name="qty" class="form-control input-number text-center" value="'.$items['qty'].'" min="0" max="100">
<span class="input-group-btn">
<button type="button" id="'.$items['rowid'].'" class="add_one_product btn btn-default btn-number" style="border: 1px solid #892826; color: white; background: #892826;"><span class="glyphicon glyphicon-plus"></span>
</button>
</span>
</div>
</td>
<td class="font-weight-bold" style="padding-top:40px;font-size: 17px;font-family: ProximaNova;letter-spacing: 1px;">RM '.number_format($items['subtotal'],2).'</td>
</tr>
';
}
$output .= '
<tr>
<th style="width:10%;"></th>
<td style="width:10%;"></td>
<td style="width:10%;"></td>
<td style="width:70%;"><h3 style="margin-right: 60px; font-size: 24px; font-weight:bold;margin-top:5px;font-family: ProximaNova;letter-spacing: 1px;">'.'TOTAL: RM '.number_format($this->cart->total(),2).'</h3></td>
</tr>
';
return $output;
}
function add_one_product() {
$rowid = $this->input->post('row_id');
$cart=$this->cart->contents();
foreach ($cart as $items) {
if($rowid == $items['rowid']){
$qty = $items['qty'];
}
}
$data = array(
'rowid' => $rowid,
'qty' => $qty + 1,
);
$this->cart->update($data);
echo $this->show_cart();
}
function remove_one_product() {
$rowid = $this->input->post('row_id');
$cart=$this->cart->contents();
foreach ($cart as $items) {
if($rowid == $items['rowid']){
$qty = $items['qty'];
}
}
$data = array(
'rowid' => $rowid,
'qty' => $qty - 1,
);
$this->cart->update($data);
echo $this->show_cart();
}
At this point the buttons and functions with the classes and names of add_one_product & remove_one_product is identical, save the naming convention and the + 1 versus -1 operation it does to the quantity of the products in the cart.
In the show_cart function as well the buttons are called and to help with visibility I will recrop them out here again:
<div class="input-group w-30" style="padding-top: 25px;">
<span class="input-group-btn">
<button type="button" id="'.$items['rowid'].'" class="remove_one_product btn btn-default btn-number" style="border: 1px solid #892826; color: white; background: #892826;"><span class="glyphicon glyphicon-minus"></span>
</button>
</span>
<input type="text" style="border: 1px solid #892826" name="qty" class="form-control input-number text-center" value="'.$items['qty'].'" min="0" max="100">
<span class="input-group-btn">
<button type="button" id="'.$items['rowid'].'" class="add_one_product btn btn-default btn-number" style="border: 1px solid #892826; color: white; background: #892826;"><span class="glyphicon glyphicon-plus"></span>
</button>
</span>
</div>
And finally in my footer, the jquery:
$(document).ready(function(){
$(document).on('click','.remove_one_product',function(){
var row_id=$(this).attr("id");
$.ajax({
url : "<?php echo base_url('products/remove_one_product');?>",
method : "POST",
data : {row_id : row_id},
success :function(data){
$('#product_detail_cart').html(data);
$('#cart-counter').load(location.href + " #cart-counter");
$('#nav-tab').load(location.href + " #nav-tab");
$('#nav-home-tab').load(location.href + " #nav-home-tab");
$('#nav-profile-tab').load(location.href + " #nav-profile-tab");
}
});
});
});
$(document).ready(function(){
$(document).on('click','.add_one_product',function(){
var row_id=$(this).attr("id");
$.ajax({
url : "<?php echo base_url('products/add_one_product');?>",
method : "POST",
data : {row_id : row_id},
success :function(data){
$('#product_detail_cart').html(data);
$('#cart-counter').load(location.href + " #cart-counter");
$('#nav-tab').load(location.href + " #nav-tab");
$('#nav-home-tab').load(location.href + " #nav-home-tab");
$('#nav-profile-tab').load(location.href + " #nav-profile-tab");
}
});
});
});
I realise that this is a long post, my thanks for those who took their time to read through it. Any help and constructive criticism is welcomed.
This is one of the silliest mistakes I've made by far and I think I'm sure to make more in the future but to help save anyone else who has a similar problem, my problem was that I wrote the config for remove_one_product but I had forgotten to write the same for add_one_product.
facepalm