0
votes

I've built an add to cart process that successfully creates a "personalisation" field when the item is added to the cart. Using the standard 'add to cart' button, the page reloads and all is well. I wanted to improve the UX by making the basket update via AJAX, which I've implemented and again working ok.

However, this stops the cart item data meta from registering because the request is not defined - the hook isn't able to grab input values from the page any more. The hook I'm using to define and write the meta fields to is 'woocommerce_add_cart_item_data'

I tried creating my own separate AJAX function to define the content of the field separately, using $_SESSION instead of $_REQUEST (inspired by this answer -> how to pass ajax data to woocommerce filter?)

Unfortunately this seemingly fires after 'woocommerce_add_cart_item_data' has run, so the meta data does not come through (in fact it ends up showing on the next product added, since the variable is defined late and not accessed until the 2nd product is added).

I'd really appreciate some help with either:

(1) Amending the code so 'woocommerce_add_cart_item_data' is able to take data from the AJAX add to cart action I made, or

(2) Amend my custom AJAX call so session data is able to be applied in a timely order (unsure if this is achievable based on what I've seen so far).

// Create AJAX add to cart button
function add_cart_btn($prod) {
            echo apply_filters( 'woocommerce_loop_add_to_cart_link',
                sprintf( '<a href="%s" rel="nofollow" data-product_id="%s" data-product_sku="%s" class="single-product__details-cta button %s product_type_%s ajax_add_to_cart" name="add_to_cart">Add to bag</a>',
                    esc_url( $prod->add_to_cart_url() ),
                    esc_attr( $prod->id ),
                    esc_attr( $prod->get_sku() ),
                    $prod->is_purchasable() ? 'add_to_cart_button' : '',
                    esc_attr( $prod->product_type ),
                    esc_html( $prod->add_to_cart_text() )
                ),
            $prod );
        }
        add_cart_btn($product);



// functions.php

/* Saves field data */
function save_add_custom_info_field( $cart_item_data, $product_id ) {
    if( isset( $_REQUEST['custom_info_message'] ) ) {

        // *** $_REQUEST['custom_info_message'] not defined ***
        $cart_item_data[ 'custom_info_message' ] = $_REQUEST['custom_info_message'];
        $cart_item_data['unique_key'] = md5( microtime().rand() );
    }
    return $cart_item_data;
}
add_action( 'woocommerce_add_cart_item_data', 'save_add_custom_info_field', 10, 2 );

/* Renders field entry on cart and checkout */
function render_mssg_meta_on_cart_and_checkout( $cart_data, $cart_item = null ) {
    $custom_items = array();
    if( !empty( $cart_data ) ) {
        $custom_items = $cart_data;
    }
    if( isset( $cart_item['custom_info_message'] ) ) {
        $custom_items[] = array( "name" => 'Personalisation / Customisation', "value" => $cart_item['custom_info_message'] );
}
    return $custom_items;
}
add_filter( 'woocommerce_get_item_data', 
'render_mssg_meta_on_cart_and_checkout', 10, 2 );


// *** Attempted solution with AJAX - Use $_SESSION['message'] in 'save_add_custom_info_field' function above instead of $_REQUEST... delivered after 'woocommerce_add_cart_item_data' so doesn't work

function set_customised_message() {

    $message = $_POST['message'];

    define( 'DOING_AJAX', true );
    if ( ! defined( 'WP_ADMIN' ) ) {
        define( 'WP_ADMIN', true );
    }

    session_start();
    $_SESSION['message'] = $message;

    echo $message;

    die();

}

I expect custom meta to show on the cart/checkout pages, but it isn't due to the variable being either $cart_item['custom_info_message'] being undefined, or session variable from AJAX call not being available.

1

1 Answers

0
votes

I've managed to solve this by updating the product meta data after it is added to the cart (via AJAX) - amending set_customised_message function above. Note the AJAX call required a timeout delay of 1s in order to work.

Leaving it here in case anyone else is having a similar issue.

function set_customised_message() {
    $cart = WC()->cart->cart_contents;

 foreach( $cart as $cart_item_id=>$cart_item ) {
     echo $cart_item['unique_key'];
 $cart_item['custom_info_message'] = $message;
 echo $cart_item['custom_info_message'];
 WC()->cart->cart_contents[$cart_item_id] = $cart_item;
 }
 WC()->cart->set_session();
}

Thanks to https://pluginrepublic.com/how-to-update-existing-woocommerce-cart-meta-data/ for this solution