Skip to content
Advertisement

WooCommerce: Avoid checkout If all cart item custom fields are not filled in

I wrote a function that disables the ordering button when additional fields (with display in cart) in each of the products have not been completed (fields appear only if there are more than 2 items in the cart).

function disable_checkout_button_no_shipping() {
    global $woocommerce;
    $quantity = $woocommerce->cart->cart_contents_count;        
 
    if( $quantity > 1 ){
        foreach ( WC()->cart->get_cart() as $cart_item ) {
            $item_name = $cart_item['data']->get_title();
            $notes = $cart_item['notes'];
            printf("[%s]n",      $notes);

            if ( empty( $notes ) ) {
                remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
                printf(
                    '<div class="wc-cart-note-warning"><span>Przed złożeniem zamówienia dodaj informację dla kogo jest kartka!</span></div>',
                );
            }
        }
    }
}
add_action( 'woocommerce_proceed_to_checkout', 'disable_checkout_button_no_shipping', 1 );

But it only works when the page is refreshed in the browser.

How can I make the function refresh every time something is entered in the text field assigned to the product and the section with the order button will be refreshed with ajax?

Below is the code that is responsible for adding notes:

Javascrit code saved under update-cart-item-ajax.js file name (custom file):

(function($) {
    // $(document).ready(function(){
    $('.prefix-cart-notes').on('change keyup paste', function() {
        $('.cart_totals').block({
            message: null,
            overlayCSS: {
                background: '#fff',
                opacity: 0.6
            }
        });
        var cart_id = $(this).data('cart-id');
        $.ajax({
            type: 'POST',
            url: prefix_vars.ajaxurl,
            data: {
                action: 'prefix_update_cart_notes',
                security: $('#woocommerce-cart-nonce').val(),
                notes: $('#cart_notes_' + cart_id).val(),
                cart_id: cart_id
            },
            success: function(response) {
                $('.cart_totals').unblock();
            }
        })
    });
});

PHP code saved in active theme functions.php file:

/**
 * Add a text field to each cart item
 */
function prefix_after_cart_item_name( $cart_item, $cart_item_key ) {
    $notes = isset( $cart_item['notes'] ) ? $cart_item['notes'] : '';
    global $woocommerce;
    $quantity = $woocommerce->cart->cart_contents_count;
    if( $quantity > 1 ){
        printf(
            '<div><textarea rows="1"  placeholder="Dla kogo jest kartka?" maxlength="30" class="%s" id="cart_notes_%s" data-cart-id="%s">%s</textarea></div>',
            'prefix-cart-notes',
            $cart_item_key,
            $cart_item_key,
            $notes
        );
    }
}
add_action( 'woocommerce_after_cart_item_name', 'prefix_after_cart_item_name', 10, 2 );

/**
 * Enqueue our JS file
 */
function prefix_enqueue_scripts() {
    //trailingslashit( plugin_dir_url( __FILE__ ) )
    wp_register_script( 'prefix-script', trailingslashit( get_home_url() ) . '/wp-content/themes/boomb_theme/assets/update-cart-item-ajax.js', array( 'jquery-blockui' ), time(), true );
    wp_localize_script(
        'prefix-script',
        'prefix_vars',
        array(
            'ajaxurl' => admin_url( 'admin-ajax.php' )
        )
    );
    wp_enqueue_script( 'prefix-script' );
}
add_action( 'wp_enqueue_scripts', 'prefix_enqueue_scripts' );

/**
 * Update cart item notes
 */
function prefix_update_cart_notes() {
    // Do a nonce check
    if( ! isset( $_POST['security'] ) || ! wp_verify_nonce( $_POST['security'], 'woocommerce-cart' ) ) {
        wp_send_json( array( 'nonce_fail' => 1 ) );
        exit;
    }

    // Save the notes to the cart meta
    $cart = WC()->cart->cart_contents;
    $cart_id = $_POST['cart_id'];
    $notes = $_POST['notes'];
    $cart_item = $cart[$cart_id];
    $cart_item['notes'] = $notes;
    WC()->cart->cart_contents[$cart_id] = $cart_item;
    WC()->cart->set_session();
    wp_send_json( array( 'success' => 1 ) );
    exit;
}
add_action( 'wp_ajax_prefix_update_cart_notes', 'prefix_update_cart_notes' );
add_action( 'wp_ajax_nopriv_prefix_update_cart_notes', 'prefix_update_cart_notes' );

function prefix_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
    if( isset( $values['notes'] ) ) {
        $item->add_meta_data( 'notes', $values['notes'], true );
    }
}
add_action( 'woocommerce_checkout_create_order_line_item', 'prefix_checkout_create_order_line_item', 10, 4 );

Advertisement

Answer

In your case, to avoid checkout, use instead woocommerce_checkout_process dedicated hook like:

add_action( 'woocommerce_checkout_process', 'check_cart_notes_to_disable_checkout' );
function check_cart_notes_to_disable_checkout() {
    foreach ( WC()->cart->get_cart() as $cart_item ) {
        if ( ! isset($cart_item['notes']) || empty($cart_item['notes']) ) {
            $button = '<a href="'. wc_get_cart_url() .'" tabindex="1" class="button wc-forward">'. __("Back to cart", "woocommerce") .'</a>';
            wc_add_notice( $button . __("Przed złożeniem zamówienia dodaj informację dla kogo jest kartka!", "woocommerce"), 'error' );
        }
    }
}

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

enter image description here

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement