Display number of items in cart on the add to cart button

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.

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *