Enhance WooCommerce Checkout Remove Products With Ajax

by JurnalWarga.com 55 views
Iklan Headers

Hey guys! Ever wanted to give your WooCommerce checkout page a little extra oomph? Specifically, have you ever thought about adding a remove button right there on the checkout page itself, allowing customers to ditch items without having to bounce back to the cart? Well, you're in the right place! We're going to dive deep into how to implement this using Ajax, making the whole process smooth and seamless. Buckle up, let’s get started!

Why Use Ajax for Removing Products?

Before we jump into the code, let's quickly chat about why we're opting for Ajax. Imagine this: a customer is on the checkout page, ready to finalize their purchase. They spot an item they no longer want. Without Ajax, clicking a remove button would likely trigger a full page reload. This can be a bit jarring and slow, especially if the customer has a lot of items in their cart or a slower internet connection. Ajax to the rescue!

Ajax (Asynchronous JavaScript and XML) allows us to update parts of a web page without reloading the entire page. This means a smoother, faster, and more user-friendly experience. When a customer clicks the remove button, Ajax will handle the removal behind the scenes, updating the checkout totals and product list dynamically. No page reload needed! This leads to a more streamlined checkout process, keeping your customers happy and reducing the chances of abandoned carts. Let's talk about the benefits of using Ajax for removing products:

  • Improved User Experience: As mentioned, Ajax provides a smoother, faster experience. Customers can remove items instantly without waiting for the page to reload. This responsiveness makes the checkout process feel more intuitive and less cumbersome.
  • Reduced Server Load: Full page reloads put a strain on your server. By using Ajax, you're only updating the necessary parts of the page, reducing server load and improving overall website performance.
  • Enhanced Interactivity: Ajax allows for more interactive elements on your checkout page. You can display confirmation messages, update cart totals in real-time, and even offer alternative product suggestions, all without interrupting the checkout flow.
  • Increased Conversion Rates: A seamless checkout experience can directly impact your conversion rates. By making it easy for customers to manage their cart and complete their purchase, you're more likely to see those orders go through.

So, now that we're all on the same page about the awesomeness of Ajax, let's roll up our sleeves and get to the code!

The Code: Adding the Remove Button

The first step in our journey is to add a remove button to each product line on the checkout page. We'll achieve this by hooking into a WooCommerce filter. Here's the code snippet that will add the magic:

function add_delete( $product_title, $cart_item, $cart_item_key ) {

    if (  is_checkout() ) {
        /* Get Cart of the product */
        $_product = apply_filters( woocommerce_cart_item_product, $cart_item['data'], $cart_item, $cart_item_key );

        $product_id = apply_filters( woocommerce_cart_item_product_id, $cart_item['product_id'], $cart_item, $cart_item_key );

        if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( woocommerce_cart_item_visible, true, $cart_item, $cart_item_key ) ) {

            $remove_link =  sprintf(
                '<a href="%s" class="remove_from_checkout" aria-label="%s" data-cart_item_key="%s" data-product_id="%s" data-product_sku="%s">&times;</a>',
                esc_url( wc_get_cart_remove_url( $cart_item_key ) ),
                __( 'Remove this item', 'woocommerce' ),
                $cart_item_key,
                esc_attr( $product_id ),
                esc_attr( $_product->get_sku() )
            );

            return $product_title . $remove_link;

        }

    }

    return $product_title;
}
add_filter( 'woocommerce_cart_item_name', 'add_delete', 10, 3 );

Let's break down this code, piece by piece, so you understand exactly what's happening:

  • function add_delete( $product_title, $cart_item, $cart_item_key ): This defines our function, which takes three arguments:
    • $product_title: The title of the product.
    • $cart_item: An array containing information about the cart item.
    • $cart_item_key: A unique key for the cart item.
  • if ( is_checkout() ): This conditional statement ensures that our code only runs on the checkout page. We don't want to add the remove button anywhere else.
  • $_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );: This line retrieves the product object from the cart item data. We use the woocommerce_cart_item_product filter to ensure compatibility with other plugins.
  • $product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );: This gets the product ID from the cart item.
  • if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) ): This is a crucial conditional statement that checks:
    • If the product exists.
    • If the product is in stock.
    • If the product quantity is greater than zero.
    • If the cart item is visible (another filter for compatibility). If all these conditions are met, we proceed to add the remove button.
  • $remove_link = sprintf(...): This is where the magic happens! We use sprintf to create the HTML for our remove button. Let's dissect this further:
    • <a href="%s" class="remove_from_checkout" ...>: This creates an anchor tag (a link). We've added a class remove_from_checkout, which we'll use later to target the button with JavaScript.
    • aria-label="%s": This adds an accessibility label to the button, which is important for users with screen readers.
    • data-cart_item_key="%s" data-product_id="%s" data-product_sku="%s": These are data attributes. We're storing the cart item key, product ID, and product SKU directly on the button. This information will be crucial when we handle the Ajax request.
    • esc_url( wc_get_cart_remove_url( $cart_item_key ) ): This generates the URL to remove the item from the cart. WooCommerce provides a handy function, wc_get_cart_remove_url, to handle this.
    • __( 'Remove this item', 'woocommerce' ): This is a translation function, ensuring our button text is translatable into other languages.
    • &times;: This is the HTML entity for the multiplication sign (×), which we're using as the button's visual representation.
  • return $product_title . $remove_link;: We append the remove button HTML to the product title and return the combined string.
  • add_filter( 'woocommerce_cart_item_name', 'add_delete', 10, 3 );: This is the final piece of the puzzle. We're using the add_filter function to hook our add_delete function into the woocommerce_cart_item_name filter. This filter is responsible for displaying the product name on the cart and checkout pages. By hooking into it, we can modify the product name output to include our remove button.

Phew! That was a lot, right? But hopefully, you now have a solid understanding of how this code works. Make sure to add this code to your theme's functions.php file or a custom plugin.

The JavaScript: Handling the Ajax Request

Now that we have our remove buttons in place, it's time to make them functional. We'll use JavaScript and Ajax to handle the removal process. Here's the JavaScript code we'll be using:

jQuery(document).ready(function($) {
    $(document).on('click', '.remove_from_checkout', function(e) {
        e.preventDefault();

        var cart_item_key = $(this).data('cart_item_key');
        var product_id = $(this).data('product_id');
        var product_sku = $(this).data('product_sku');
        var remove_button = $(this);

        $.ajax({
            type: 'POST',
            url: wc_checkout_params.ajax_url,
            data: {
                action: 'remove_from_checkout',
                cart_item_key: cart_item_key,
                product_id: product_id,
                product_sku: product_sku
            },
            beforeSend: function() {
                remove_button.closest('tr.woocommerce-cart-form__cart-item').block({
                    message: null,
                    overlayCSS: {
                        background: '#fff',
                        opacity: 0.6
                    }
                });
            },
            success: function(response) {
                if ( response.fragments ) {
                    $.each( response.fragments, function( key, value ) {
                        $(key).replaceWith( value );
                    });
                }
                $( document.body ).trigger( 'wc_fragment_refresh' );
            },
            complete: function() {
                remove_button.closest('tr.woocommerce-cart-form__cart-item').unblock();
            }
        });
    });
});

Alright, let's break down this JavaScript code, line by line, so we know exactly what's going on:

  • jQuery(document).ready(function($) { ... });: This is the standard jQuery document ready function. It ensures that our code runs after the DOM (Document Object Model) is fully loaded.
  • $(document).on('click', '.remove_from_checkout', function(e) { ... });: This is an event listener. It listens for click events on elements with the class remove_from_checkout (our remove buttons). We use $(document).on() because the checkout page might be loaded via Ajax, and we need to bind the event listener to elements that might not exist yet.
    • e.preventDefault();: This prevents the default link behavior (which would be to navigate to the URL in the href attribute). We want to handle the removal with Ajax.
  • var cart_item_key = $(this).data('cart_item_key');, var product_id = $(this).data('product_id');, var product_sku = $(this).data('product_sku');: These lines retrieve the data attributes we stored on the remove button earlier. Remember, we stored the cart item key, product ID, and product SKU as data attributes.
  • var remove_button = $(this);: This stores a reference to the clicked button. We'll use this later to add a loading overlay and unblock the row after the Ajax request is complete.
  • $.ajax({ ... });: This is the core of our Ajax request. We're using jQuery's $.ajax() function to send a POST request to the server.
    • type: 'POST': We're sending a POST request.
    • url: wc_checkout_params.ajax_url: This is the URL for the Ajax endpoint. WooCommerce provides this URL through the wc_checkout_params object. This object is automatically enqueued when WooCommerce scripts are loaded on the checkout page. You will need to make sure that woocommerce_checkout script is enqueued on your checkout page. This is normally done by Woocommerce. If you do not see wc_checkout_params you will need to enqueue the script.
    • data: { ... }: This is the data we're sending to the server. Let's break this down:
      • action: 'remove_from_checkout': This is the Ajax action we'll be using on the server-side to handle the removal. We'll define this action in our functions.php file.
      • cart_item_key: cart_item_key, product_id: product_id, product_sku: product_sku: We're sending the cart item key, product ID, and product SKU to the server. This information will be used to identify and remove the correct item from the cart.
    • beforeSend: function() { ... }: This function is executed before the Ajax request is sent. We're using it to add a loading overlay to the product row. This gives the user visual feedback that something is happening.
      • remove_button.closest('tr.woocommerce-cart-form__cart-item').block({ ... });: We're using the blockUI plugin (which is included with WooCommerce) to block the product row. This prevents the user from interacting with the row while the Ajax request is in progress.
      • message: null: We don't want to display any message in the overlay.
      • overlayCSS: { ... }: We're setting the CSS for the overlay to a semi-transparent white background.
    • success: function(response) { ... }: This function is executed if the Ajax request is successful. The response argument contains the data returned from the server.
      • if ( response.fragments ) { ... }: We're checking if the response contains a fragments property. WooCommerce often uses fragments to update parts of the page via Ajax. Fragments are HTML snippets that replace specific elements on the page.
        • $.each( response.fragments, function( key, value ) { ... });: We're looping through the fragments and replacing the corresponding elements on the page.
          • $(key).replaceWith( value );: This replaces the element with the selector key with the HTML value.
      • $( document.body ).trigger( 'wc_fragment_refresh' );: This triggers the wc_fragment_refresh event. This event is used by other WooCommerce scripts to update parts of the page after Ajax updates.
    • complete: function() { ... }: This function is executed after the Ajax request is complete, regardless of whether it was successful or not. We're using it to unblock the product row and remove the loading overlay.
      • remove_button.closest('tr.woocommerce-cart-form__cart-item').unblock();: We're using the unblock() function from the blockUI plugin to unblock the product row.

This JavaScript code is responsible for listening for clicks on our remove buttons, sending an Ajax request to the server, and updating the checkout page with the response. Make sure to enqueue this script in your theme's functions.php file or a custom plugin. You'll need to make sure you enqueue this script after the woocommerce_checkout script so wc_checkout_params is available. Here's an example of how to enqueue the script:

function enqueue_checkout_script() {
    if ( is_checkout() ) {
        wp_enqueue_script( 'checkout-remove-script', get_stylesheet_directory_uri() . '/js/checkout-remove.js', array( 'jquery', 'wc-checkout' ), null, true );
    }
}
add_action( 'wp_enqueue_scripts', 'enqueue_checkout_script' );

The PHP: Handling the Ajax Action

We've got our remove buttons and our JavaScript Ajax request all set up. Now, we need to handle the Ajax request on the server-side. We'll do this by defining an Ajax action in our functions.php file. Here's the code:

function remove_from_checkout() {
    $cart_item_key = $_POST['cart_item_key'];

    if ( ! $cart_item_key ) {
        wp_send_json_error( 'No cart item key provided' );
        wp_die();
    }

    WC()->cart->remove_cart_item( $cart_item_key );

    $fragments = WC()->cart->get_refreshed_fragments();

    wp_send_json_success( array(
        'fragments' => $fragments
    ) );

    wp_die();
}

add_action( 'wp_ajax_remove_from_checkout', 'remove_from_checkout' );
add_action( 'wp_ajax_nopriv_remove_from_checkout', 'remove_from_checkout' );

Let's break this PHP code down:

  • function remove_from_checkout() { ... }: This defines our function that will handle the Ajax request.
  • $cart_item_key = $_POST['cart_item_key'];: We're retrieving the cart_item_key from the POST data. This is the key we sent from our JavaScript.
  • if ( ! $cart_item_key ) { ... }: We're checking if the cart_item_key is empty. If it is, we send an error response and exit.
    • wp_send_json_error( 'No cart item key provided' );: This is a WordPress function that sends a JSON error response.
    • wp_die();: This is a WordPress function that terminates the current script execution.
  • WC()->cart->remove_cart_item( $cart_item_key );: This is the crucial line! We're using the remove_cart_item() method from the WooCommerce cart object to remove the item from the cart. We pass the cart_item_key to identify the item to remove.
  • $fragments = WC()->cart->get_refreshed_fragments();: This is where we get the fragments to update the checkout page. WooCommerce provides the get_refreshed_fragments() method, which returns an array of HTML snippets that need to be updated.
  • wp_send_json_success( array( 'fragments' => $fragments ) );: We're sending a JSON success response back to the client. We include the fragments in the response so the JavaScript can update the checkout page.
  • wp_die();: We terminate the script execution after sending the response.
  • add_action( 'wp_ajax_remove_from_checkout', 'remove_from_checkout' );: This hooks our remove_from_checkout function into the wp_ajax_remove_from_checkout action. This action is triggered when an authenticated user sends an Ajax request with the action parameter set to remove_from_checkout.
  • add_action( 'wp_ajax_nopriv_remove_from_checkout', 'remove_from_checkout' );: This hooks our remove_from_checkout function into the wp_ajax_nopriv_remove_from_checkout action. This action is triggered when a non-authenticated user (a guest) sends an Ajax request with the action parameter set to remove_from_checkout. We need to hook into both actions to support both logged-in users and guests.

This PHP code is the server-side logic that handles the Ajax request to remove an item from the cart. It receives the cart_item_key, removes the item from the cart, and sends back fragments to update the checkout page.

Conclusion: You Did It!

Woohoo! You've successfully added remove buttons to your WooCommerce checkout page using Ajax! This is a fantastic way to improve the user experience and make the checkout process smoother for your customers. You have to congratulate yourself for following along this guide.

We covered a lot in this article, from the benefits of using Ajax to the nitty-gritty details of the code. You learned how to:

  • Add remove buttons to the checkout page using a WooCommerce filter.
  • Handle Ajax requests with JavaScript.
  • Process the Ajax request on the server-side with PHP.
  • Update the checkout page using WooCommerce fragments.

Now, go forth and implement this on your own WooCommerce store! Your customers will thank you for it.

If you have any questions or run into any issues, feel free to ask in the comments below. And remember, practice makes perfect! The more you work with Ajax and WooCommerce, the more comfortable you'll become. Keep experimenting and keep learning!