Asked  7 Months ago    Answers:  5   Viewed   345 times

The Problem:

I am trying to display a JavaScript alert when AJAX is called. But the alert only fires successfully when I refresh the page.

Here is the start of the function which triggers the javascript IF cart items > 2:

So if there are more than 2 items in the Woocommerce cart, run the Javascript alert...

add_action( 'wp_footer', 'trigger_popup' );
function trigger_popup() {

  global $woocommerce;
  $maximum_num_products = 2;
  $cart_num_products = WC()->cart->get_cart_contents_count();

        if( $cart_num_products > $maximum_num_products ) {

Then I am trying to display the javascript alert when ajax is called:

I researched Global Ajax Event Handlers and I think $.ajaxComplete is whats needed, but it doesn't trigger the javascript. I'm also trying to set the URL Ajax JS Handler in an attempt to trigger the alert...

    ?>
<script src="https://unpkg.com/sweetalert2@7.20.1/dist/sweetalert2.all.js"></script>
        <script type="text/javascript">

                //EXECUTE FOR AJAX?
                $( document ).ajaxComplete(function(){

                //URL NEEDED FOR AJAX TO WORK?
                  url: '/?wc-ajax=add_to_cart',

                    // ALERT CODE HERE
                  swal(
                    'You added all the items!',
                    'Proceed to checkout?',
                    'success')
                    //END OF ALERT CODE

        })(jQuery);
        </script>

<?php
  }
}       

As FYI, This is the working version of the Javascript triggers the alert ON PAGE REFRESH, but not for AJAX:

If there are more than 2 items in the cart, AND I refresh the page. This successfully triggers the javascript alert.

    ?>
<script src="https://unpkg.com/sweetalert2@7.20.1/dist/sweetalert2.all.js"></script>
        <script type="text/javascript">
                  swal(
                    'You added all the items!',
                    'Proceed to checkout?',
                    'success')
        </script>
<?php
  }
}

How can I get the Javascript alert to trigger on Ajax OR check if the IF conditions have been met, each time Ajax is called?

Thanks!

 Answers

10

Try the following code where jQuery code will send an ajax request on "added_to_cart" delegated event. On that request php will get the cart item count and will return it to jQuery. If that count met some condition, it will display your sweet-alert message:

// Wordpress Ajax: Get different cart items count
add_action( 'wp_ajax_nopriv_checking_cart_items', 'checking_cart_items' );
add_action( 'wp_ajax_checking_cart_items', 'checking_cart_items' );
function checking_cart_items() {
    if( isset($_POST['added']) ){
        // For 2 different cart items
        echo json_encode( sizeof( WC()->cart->get_cart() ) );
    }
    die(); // To avoid server error 500
}

// The Jquery script
add_action( 'wp_footer', 'custom_popup_script' );
function custom_popup_script() {
    ?>
    <script src="https://unpkg.com/sweetalert2@8.8.1/dist/sweetalert2.all.min.js"></script>
    <script src="https://unpkg.com/promise-polyfill@8.1.0/dist/polyfill.min.js"></script>
    <script type="text/javascript">
    jQuery( function($){
        // The Ajax function
        $(document.body).on('added_to_cart', function() {
            console.log('event');
            $.ajax({
                type: 'POST',
                url: wc_add_to_cart_params.ajax_url,
                data: {
                    'action': 'checking_cart_items',
                    'added' : 'yes'
                },
                success: function (response) {
                    if( response >= 2 ){
                        swal(
                            'You added all the items!',
                            'Proceed to checkout?',
                            'success'
                        );
                    }
                }
            });
        });
    });
    </script>
    <?php
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

enter image description here

Wednesday, March 31, 2021
 
talkhabi
answered 7 Months ago
77

To display and save custom meta data added to cart in cart, checkout and orders when using:

WC()->cart->add_to_cart( $product_id ,1,  0,array(), array('add_size' => array('PR CODE'=>'1.0') );

You will use the following code:

// Display custom cart item meta data (in cart and checkout)
add_filter( 'woocommerce_get_item_data', 'display_cart_item_custom_meta_data', 10, 2 );
function display_cart_item_custom_meta_data( $item_data, $cart_item ) {
    $meta_key = 'PR CODE';
    if ( isset($cart_item['add_size']) && isset($cart_item['add_size'][$meta_key]) ) {
        $item_data[] = array(
            'key'       => $meta_key,
            'value'     => $cart_item['add_size'][$meta_key],
        );
    }
    return $item_data;
}

// Save cart item custom meta as order item meta data and display it everywhere on orders and email notifications.
add_action( 'woocommerce_checkout_create_order_line_item', 'save_cart_item_custom_meta_as_order_item_meta', 10, 4 );
function save_cart_item_custom_meta_as_order_item_meta( $item, $cart_item_key, $values, $order ) {
    $meta_key = 'PR CODE';
    if ( isset($values['add_size']) && isset($values['add_size'][$meta_key]) ) {
        $item->update_meta_data( $meta_key, $values['add_size'][$meta_key] );
    }
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

Example display on Cart (and Checkout) pages:

enter image description here

Example display on Orders (and email notifications):

enter image description here

Wednesday, March 31, 2021
 
khaverim
answered 7 Months ago
58

To make it work for 2 different product categories displaying a Sweet alert when 5 items from one of those product categories have been added to cart:

// Wordpress Ajax: Get different cart items count
add_action( 'wp_ajax_nopriv_checking_items', 'checking_cart_items' );
add_action( 'wp_ajax_checking_items', 'checking_cart_items' );
function checking_cart_items() {
    if( isset($_POST['id']) && $_POST['id'] > 0 ){
        // Initialising variables
        $counts     = array();
        $product_id = $_POST['id'];
        $categories = array('bags', 'shoes');

        // Loop through cart for product categories count
        foreach ( WC()->cart->get_cart() as $cart_item ) {
            if ( has_term( $categories[0], 'product_cat', $cart_item['product_id'] ) )
               $counts[0] += $cart_item['quantity'];
            if ( has_term( $categories[1], 'product_cat', $cart_item['product_id'] ) )
               $counts[1] += $cart_item['quantity'];
        }

        // Return the product category count that belongs to the added item
        if( has_term( $categories[0], 'product_cat', $product_id ) )
            echo json_encode(array( strtoupper($categories[0]) => $counts[0])); // Returned value to jQuery
        if( has_term( $categories[1], 'product_cat', $product_id ) )
            echo json_encode(array( strtoupper($categories[1]) => $counts[1])); // Returned value to jQuery
    }

    die(); // To avoid server error 500
}

// The Jquery script
add_action( 'wp_footer', 'items_check' );
function items_check() {
    if(is_checkout()) return; // Except on checkout page
    ?>
    <script src="https://unpkg.com/sweetalert2@7.20.1/dist/sweetalert2.all.js"></script>
    <script type="text/javascript">
    jQuery( function($){
        // wc_add_to_cart_params is required to continue
        if ( typeof wc_add_to_cart_params === 'undefined' )
            return false;

        $(document.body).on( 'added_to_cart', function( event, fragments, cart_hash, $button ) {
            // The Ajax request
            $.ajax({
                type: 'POST',
                url: wc_add_to_cart_params.ajax_url,
                data: {
                    'action': 'checking_items',
                    'id'    : $button.data('product_id') // Send the product ID
                },
              //ONLY DISPLAY ALERT IF TOTAL ITEMS IS FROM CATEGORY BAGS
                success: function (response) {
                    $.each( JSON.parse(response), function( category, count ) {
                        if( count == 5 ){
                            // Display javascript alert
                            const toast = swal.mixin({
                              toast: true,
                              showConfirmButton: false,
                              timer: 3000
                            });
                            toast({
                              type: 'success',
                              title: "You've added 5 "+category+"!"
                            });
                        }
                        // The below line is just for testing: to be removed
                        console.log('category: '+category+' | count: '+count);
                    });
                }
            });
        });
    });
    </script>
    <?php
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

enter image description here

Saturday, May 29, 2021
 
njai
answered 5 Months ago
26

You should not use any reload to update the cart content count… Instead you should use the dedicated woocommerce_add_to_cart_fragments action hook that is Ajax powered.

1) The HTML to be refreshed: So first in your theme's header.php file you should need to embed the cart count in a specific html tag with a defined unique ID (or a class), for example something like:

$items_count = WC()->cart->get_cart_contents_count(); 
?>
    <div id="mini-cart-count"><?php echo $items_count ? $items_count : '&nbsp;'; ?></div>
<?php

or:

$items_count = WC()->cart->get_cart_contents_count();

echo '<div id="mini-cart-count"><?php echo $items_count ? $items_count : '&nbsp;'; ?></div>';

2) The code:

add_filter( 'woocommerce_add_to_cart_fragments', 'wc_refresh_mini_cart_count');
function wc_refresh_mini_cart_count($fragments){
    ob_start();
    $items_count = WC()->cart->get_cart_contents_count();
    ?>
    <div id="mini-cart-count"><?php echo $items_count ? $items_count : '&nbsp;'; ?></div>
    <?php
        $fragments['#mini-cart-count'] = ob_get_clean();
    return $fragments;
}

if you use a class in your html Tag, you will replace ['#mini-cart-count'] by ['.mini-cart-count']. This hook is also used to refresh the mini-cart content.

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

Since few years global $woocommerce; + $woocommerce->cart is outdated and replaced by WC()->cart to access WooCommerce cart object.


If you need jQuery to force refresh that count, you can try wc_fragment_refresh or wc_fragments_refreshed delegated events, like:

$(document.body).trigger('wc_fragment_refresh');

or:

$(document.body).trigger('wc_fragments_refreshed');
Monday, June 14, 2021
 
ALH
answered 4 Months ago
ALH
53

Okay so I figured it out! I can now update cart item's quantities without refreshing via AJAX (:

my functions.php looks like this

//Enqueue Ajax Scripts
function enqueue_cart_qty_ajax() {

    wp_register_script( 'cart-qty-ajax-js', get_template_directory_uri() . '/js/cart-qty-ajax.js', array( 'jquery' ), '', true );
    wp_localize_script( 'cart-qty-ajax-js', 'cart_qty_ajax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
    wp_enqueue_script( 'cart-qty-ajax-js' );

}
add_action('wp_enqueue_scripts', 'enqueue_cart_qty_ajax');

function ajax_qty_cart() {

    // Set item key as the hash found in input.qty's name
    $cart_item_key = $_POST['hash'];

    // Get the array of values owned by the product we're updating
    $threeball_product_values = WC()->cart->get_cart_item( $cart_item_key );

    // Get the quantity of the item in the cart
    $threeball_product_quantity = apply_filters( 'woocommerce_stock_amount_cart_item', apply_filters( 'woocommerce_stock_amount', preg_replace( "/[^0-9.]/", '', filter_var($_POST['quantity'], FILTER_SANITIZE_NUMBER_INT)) ), $cart_item_key );

    // Update cart validation
    $passed_validation  = apply_filters( 'woocommerce_update_cart_validation', true, $cart_item_key, $threeball_product_values, $threeball_product_quantity );

    // Update the quantity of the item in the cart
    if ( $passed_validation ) {
        WC()->cart->set_quantity( $cart_item_key, $threeball_product_quantity, true );
    }

    // Refresh the page
    echo do_shortcode( '[woocommerce_cart]' );

    die();

}

add_action('wp_ajax_qty_cart', 'ajax_qty_cart');
add_action('wp_ajax_nopriv_qty_cart', 'ajax_qty_cart');

My cart-qty-ajax.js looks like this.

jQuery( function( $ ) {

    $( document ).on( 'change', 'input.qty', function() {

        var item_hash = $( this ).attr( 'name' ).replace(/cart[([w]+)][qty]/g, "$1");
        var item_quantity = $( this ).val();
        var currentVal = parseFloat(item_quantity);

        function qty_cart() {

            $.ajax({
                type: 'POST',
                url: cart_qty_ajax.ajax_url,
                data: {
                    action: 'qty_cart',
                    hash: item_hash,
                    quantity: currentVal
                },
                success: function(data) {
                    $( '.view-cart-popup' ).html(data);
                }
            });  

        }

        qty_cart();

    });

});

Works beautifully, though I'm not sure if this is 'good practice'. Thanks all!

Tuesday, August 10, 2021
 
phpmeh
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :