In today’s tutorial we’ll be modifying the text of the add to cart button to display any already added items in the cart, instead of just the usual ‘Add to cart’ text, giving our customers more information regarding their upcoming purchases.
Install and activate a child theme
The first step on our process here is to create and install a child theme. If you are using one of our themes you can easily grab its child theme from our downloads section. If not, you can read our beginner’s guide on child themes to create your own. This step is essential in order to preserve our changes throughout theme updates.
All code below will be placed in our child theme’s functions.php file. If the file is empty the code will go just below the opening <?php tag, otherwise, if it has contents, the code should be placed at the end of the file, before the closing ?> PHP tag if it exists.
Replacing the button text
Our first step is to replace the normal button text with the number of products in the cart for simple and variable products in product listings and the single product view. To do that we will use the woocommerce_product_add_to_cart_text and the woocommerce_product_single_add_to_cart_text hooks for the listing add to cart and the single add to cart button respectively.
add_filter( 'woocommerce_product_add_to_cart_text', 'cssigniter_button_text_modifier' );
add_filter( 'woocommerce_product_single_add_to_cart_text', 'cssigniter_button_text_modifier' );
function cssigniter_button_text_modifier( $text ) {
global $product;
if ( ! $product ) {
return $text;
}
$product_id = $product->get_ID();
$quantities = WC()->cart->get_cart_item_quantities();
$quantity = 0;
if ( empty( $quantities ) ) {
return $text;
}
if ( 'simple' === $product->get_type() ) {
if ( in_array( $product_id, array_keys( $quantities ), true ) ) {
$quantity += $quantities[ $product_id ];
}
return $quantity > 0 ? $quantity . __( ' in cart', 'your-text-domain' ) : $text;
} elseif ( 'variable' === $product->get_type() ) {
$children = $product->get_children();
foreach ( $children as $child => $id ) {
if ( in_array( $id, array_keys( $quantities ), true ) ) {
$quantity += $quantities[ $id ];
}
}
return $quantity > 0 ? $quantity . __( ' in cart', 'your-text-domain' ) : $text;
}
return $text;
}
In our code above we pull the cart quantities, this will give us back an array of product ids along with their respective cart quantities, if this returns nothing we stop there. For simple products we check if the product id is among the ones returned in the cart contents, if it is we add its quantity in a variable and return it as the button’s text, if the product is not among the cart’s contents we return the default text. Similarly for variable products, we check if any child product (or variation) is among the cart’s contents, if it is we follow the same procedure as with simple products.
Quantities added to the cart appear on the add to cart button.
Quantities in the cart shown on the single add to cart button.
Now any quantity of a particular product added in the cart will appear on the add to cart button as well.
Using AJAX to update the button text in real time
Our initial goal is achieved, however we can go a step further. As it stands now, if a product is added to the cart from the listing page, we will need to refresh the page in order for the number of items is removed. Similarly if our theme supports an AJAX based minicart, removing items from the minicart would also need a page refresh in order to be reflected on the button text. To achieve that we will need some AJAX goodness.
add_action('wp_footer', 'cssigniter_change_add_to_cart_text_js', 99);
function cssigniter_change_add_to_cart_text_js() {
if ( ! is_woocommerce() ) {
return;
}
?>
<script type="text/javascript">
(function($) {
$(document).on('click', '.ajax_add_to_cart, .remove_from_cart_button', function(e) {
var clicked = $(this);
var productId = $(this).data("product_id");
var isRemoval = $(this).hasClass('remove_from_cart_button');
var button = $(document).find('a[data-product_id=' + productId + '].add_to_cart_button');
var singleButton = $('.single_add_to_cart_button');
$.post("<?php echo admin_url( 'admin-ajax.php' ); ?>", {
action: "cssigniter-add-to-cart-text-changer",
id: productId,
removal: true == isRemoval ? 1 : 0,
})
.done(function(data) {
$(button).text(data);
$(singleButton).text(data);
if (isRemoval) {
$(button).siblings('.added_to_cart').remove();
}
});
});
})(jQuery);
</script>
<?php
}
add_action( 'wp_ajax_cssigniter-add-to-cart-text-changer', 'cssigniter_change_add_to_cart_text', 99 );
add_action( 'wp_ajax_nopriv_cssigniter-add-to-cart-text-changer', 'cssigniter_change_add_to_cart_text', 99 );
function cssigniter_change_add_to_cart_text() {
$product_id = $_POST['id'];
$is_removal = $_POST['removal'];
$quantities = WC()->cart->get_cart_item_quantities();
$product = wc_get_product( $product_id );
if ( 'simple' === $product->get_type() ) {
$quantity = 1;
$default_text = __( 'Add to cart', 'your-text-domain' );
if ( 0 === absint( $is_removal ) ) {
if ( in_array( absint( $product_id ), array_keys( $quantities ), true ) ) {
$quantity += $quantities[ $product_id ];
}
$quantity = $quantity . __( ' in cart', 'your-text-domain' );
echo esc_html( $quantity );
} else {
echo esc_html( $default_text );
}
} elseif ( 'variable' === $product->get_type() && 1 === absint( $is_removal ) ) {
$children = $product->get_children();
$default_text = __( 'Select options', 'your-text-domain' );
$quantity = 0;
foreach ( $children as $child => $id ) {
if ( in_array( $id, array_keys( $quantities ), true ) ) {
$quantity += $quantities[ $id ];
}
}
$quantity--;
echo $quantity > 0 ? absint( $quantity ) . esc_html__( ' in cart', 'your-text-domain' ) : esc_html( $default_text );
}
wp_die();
}
First up we create a small JS snippet and hook it at the site’s footer using wp_footer. The snippet detects clicks on the add to cart button and the remove from cart button for AJAX powered minicarts and calls on our text changer AJAX hook. The function cssigniter_change_add_to_cart_text ran on our hook works pretty similarly with our first function which modifies the button text, it gets the current cart contents, checks if the product in question has any products in the cart, gets the amount and returns it to be used as the add to cart button’s text. For removals it gets the cart contents makes the removal, calculates the new cart contents if applicable and creates the string which will be used as the button’s text.
Cart text automatically updates when new items are added to the cart.
Removing items from the cart updates the button text.
Works for variations added to the cart as well.
Wrapping up
We have successfully made cart quantities for each product appear on the add to cart button for product listing & single product views. Do you think this is a useful feature? Let us know in the comments below.
6 responses to “Display number of items in cart on the add to cart button”
Hello Single product page not working please solution provide ASPS
Website opetion my link add please check and solution provide
Not working page link:- https://zobo.aksharm.co.in/product/armor-twist/
Hello Nimita.
Did you use the code provided on the post or is it just that a product does not work? If you did use the code and you think it caused the issue, try removing it and see if it fixes itself.
Great idea! But it doesn’t work for me when I add a list of products to a simple page using Gutenberg. And for variable products, the button is not updated if you delete an item from the basket. Can you fix it?
Hello.
Thank you for letting us know. We’ll take a look at these issues and update the post if necessary.
Hi Nik! Thank you for this great article! It is possible to have something similar but as text or a badge with the qty added on a corner of the Add to cart button instead to change the text? What hooks/actions I need to use?
Hello.
Glad to hear you like this article. Adding proper badges to the buttons is quite more complex, it would require you to modify the template parts for the loop’s add to cart buttons, along with the ones for the single product to include the badge and then use AJAX to update the contents of the badge. I’m afraid added complexity like this one falls outside the scope of this tutorial.