简体   繁体   English

Ajax 加入购物车 WooCommerce 单品上的简单和可变产品

[英]Ajax Add to cart for simple and variable products on WooCommerce single products

The code below is working for add to cart with WooCommerce for simple products, but not for variable products.下面的代码适用于使用 WooCommerce 添加到购物车的简单产品,但不适用于可变产品。 Can someone help me out?有人可以帮我吗? Because this code works with the latest WC, please do not remove this question because there are lots of codes for this online that do not work at all.因为此代码适用于最新的 WC,请不要删除此问题,因为网上有很多代码根本不起作用。

The error I am getting that is says in a notice that I should choose a product option, even when I chose one.我得到的错误是在通知中说我应该选择一个产品选项,即使我选择了一个。

JS: JS:

jQuery(function($) {
        $('form.cart').on('submit', function(e) {
            e.preventDefault();

            var form = $(this);
            form.block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } });

            var formData = new FormData(form.context);
            formData.append('add-to-cart', form.find('[name=add-to-cart]').val() );

    var $thisbutton = form.find('.single_add_to_cart_button'); //


            // Ajax action
            $.ajax({
                url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'ace_add_to_cart' ),
                data: formData,
                type: 'POST',
                processData: false,
                contentType: false,
      beforeSend: function (response) {
           $thisbutton.removeClass('added').addClass('loading');
       },
                complete: function( response ) {
                    response = response.responseJSON;

                    if ( ! response ) {
                        return;
                    }

                    if ( response.error && response.product_url ) {
                        window.location = response.product_url;
                        return;
                    }

                    // Redirect to cart option
                    if ( wc_add_to_cart_params.cart_redirect_after_add === 'yes' ) {
                        window.location = wc_add_to_cart_params.cart_url;
                        return;
                    }

                    // Trigger event so themes can refresh other areas.
                    $( document.body ).trigger( 'added_to_cart', [ response.fragments, response.cart_hash, $thisbutton ] );

                    // Remove existing notices
                    $( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();

                    // Add new notices
                    form.closest('.product').before(response.fragments.notices_html)

                    form.unblock();
                }
            });
        });
    });

PHP: PHP:

/* WOOCOMMERCE AJAX ADD TO CART
--------------------------------------------------- */
function ace_ajax_add_to_cart_handler() {
  WC_Form_Handler::add_to_cart_action();
    WC_AJAX::get_refreshed_fragments();
}

/* Add fragments for notices. */
function ace_ajax_add_to_cart_add_fragments( $fragments ) {
    $all_notices  = WC()->session->get( 'wc_notices', array() );
    $notice_types = apply_filters( 'woocommerce_notice_types', array( 'error', 'success', 'notice' ) );

    ob_start();
    foreach ( $notice_types as $notice_type ) {
        if ( wc_notice_count( $notice_type ) > 0 ) {
            wc_get_template( "notices/{$notice_type}.php", array(
                'messages' => array_filter( $all_notices[ $notice_type ] ),
        'notices' => array_filter( $all_notices[ $notice_type ] ),
            ) );
    }
    }

    $fragments['notices_html'] = ob_get_clean();
  wc_clear_notices();
    return $fragments;
}

add_action( 'wc_ajax_ace_add_to_cart', 'ace_ajax_add_to_cart_handler' );
add_action( 'wc_ajax_nopriv_ace_add_to_cart', 'ace_ajax_add_to_cart_handler' );
remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 ); // Remove WC Core add to cart handler to prevent double-add
add_filter( 'woocommerce_add_to_cart_fragments', 'ace_ajax_add_to_cart_add_fragments' );

To enable Ajax add to cart for simple and variable products on Single product pages you need something different, building a custom Ajax add to cart function that handles also custom product fields and cart item data manipulation (what WooCommerce default Ajax add to cart doesn't allow) . To enable Ajax add to cart for simple and variable products on Single product pages you need something different, building a custom Ajax add to cart function that handles also custom product fields and cart item data manipulation (what WooCommerce default Ajax add to cart doesn't允许)

Try the following fully tested on WooCommerce version 4.9.0:在 WooCommerce 版本 4.9.0 上尝试以下完全测试:

add_action( 'wp_footer', 'single_product_ajax_add_to_cart_js_script' );
function single_product_ajax_add_to_cart_js_script() {
    ?>
    <script>
    (function($) {
        $('form.cart').on('submit', function(e) {
            e.preventDefault();

            var form   = $(this),
                mainId = form.find('.single_add_to_cart_button').val(),
                fData  = form.serializeArray();

            form.block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } });

            if ( mainId === '' ) {
                mainId = form.find('input[name="product_id"]').val();
            }

            if ( typeof wc_add_to_cart_params === 'undefined' )
                return false;

            $.ajax({
                type: 'POST',
                url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'custom_add_to_cart' ),
                data : {
                    'product_id': mainId,
                    'form_data' : fData
                },
                success: function (response) {
                    $(document.body).trigger("wc_fragment_refresh");
                    $('.woocommerce-error,.woocommerce-message').remove();
                    $('input[name="quantity"]').val(1);
                    $('.content-area').before(response);
                    form.unblock();
                    // console.log(response);
                },
                error: function (error) {
                    form.unblock();
                    // console.log(error);
                }
            });
        });
    })(jQuery);
    </script>
    <?php
}

add_action( 'wc_ajax_custom_add_to_cart', 'custom_add_to_cart_handler' );
add_action( 'wc_ajax_nopriv_custom_add_to_cart', 'custom_add_to_cart_handler' );
function custom_add_to_cart_handler() {
    if( isset($_POST['product_id']) && isset($_POST['form_data']) ) {
        $product_id = $_POST['product_id'];

        $variation = $cart_item_data = $custom_data = array(); // Initializing
        $variation_id = 0; // Initializing

        foreach( $_POST['form_data'] as $values ) {
            if ( strpos( $values['name'], 'attributes_' ) !== false ) {
                $variation[$values['name']] = $values['value'];
            } elseif ( $values['name'] === 'quantity' ) {
                $quantity = $values['value'];
            } elseif ( $values['name'] === 'variation_id' ) {
                $variation_id = $values['value'];
            } elseif ( $values['name'] !== 'add_to_cart' ) {
                $custom_data[$values['name']] = esc_attr($values['value']);
            }
        }

        $product = wc_get_product( $variation_id ? $variation_id : $product_id );

        // Allow product custom fields to be added as custom cart item data from $custom_data additional array variable
        $cart_item_data = (array) apply_filters( 'woocommerce_add_cart_item_data', $cart_item_data, $product_id, $variation_id, $quantity, $custom_data );

        // Add to cart
        $cart_item_key = WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation, $cart_item_data );

        if ( $cart_item_key ) {
            // Add to cart successful notice
            wc_add_notice( sprintf(
                '<a href="%s" class="button wc-forward">%s</a> %d &times; "%s" %s' ,
                wc_get_cart_url(),
                __("View cart", "woocommerce"),
                $quantity,
                $product->get_name(),
                __("has been added to your cart", "woocommerce")
            ) );
        }

        wc_print_notices(); // Return printed notices to jQuery response.
        wp_die();
    }
}

Code goes in functions.php file of the active child theme (or active theme).代码进入活动子主题(或活动主题)的functions.php文件。 Tested and works.测试和工作。

All notices are enable and displayed on the fly:所有通知都启用并即时显示:

在此处输入图像描述


Handling product custom fields and cart item data manipulation:处理产品自定义字段和购物车项目数据操作:

This custom Ajax add to cart code handle product custom fields, allowing to add them as custom cart item data.此自定义 Ajax 添加到购物车代码处理产品自定义字段,允许将它们添加为自定义购物车项目数据。

For that we use woocommerce_add_cart_item_data WooCommerce dedicated hook enabled in our custom Ajax add to cart code, allowing to add product custom fields as custom cart item data or manipulate cart data on the fly.为此,我们使用在我们的自定义 Ajax 添加到购物车代码中启用的woocommerce_add_cart_item_data WooCommerce 专用挂钩添加到购物车代码,允许将产品自定义字段添加为自定义购物车项目数据或动态操作购物车数据。

If we add a product custom input text field with this code:如果我们使用以下代码添加产品自定义输入文本字段:

add_action( 'woocommerce_before_add_to_cart_button', 'product_additional_custom_fields' );
function product_additional_custom_fields() {
    echo '<table class="variations" cellspacing="0" width="100px">
            <tbody><tr>
                <td class="label" style="width:100px"><label for="engraving">' . __("Engraving text") . '</label></td>
                <td class="value">
                    <input type="text" name="engraving" id="engraving" value="" />
                </td>
            </tr></tbody>
    </table>
    </br>';
}

Then if you want to pass the field value as custom cart item data, you will use然后,如果您想将字段值作为自定义购物车项目数据传递,您将使用

add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_custom_data', 10, 5 );
function add_cart_item_custom_data( $cart_item_data, $product_id, $variation_id = 0, $quantity, $custom_data = array() ) {
    if ( isset($custom_data['engraving']) && ! empty($custom_data['engraving']) ) {
        $cart_item_data['engraving'] = sanitize_text_field($custom_data['engraving']);
    }

    return $cart_item_data;
}

And you can check with the following, that will display in cart and checkout that custom cart item data:您可以检查以下内容,这将显示在购物车中并结帐该自定义购物车项目数据:

add_filter( 'woocommerce_get_item_data', 'display_on_cart_and_checkout', 10, 2 );
function display_on_cart_and_checkout( $cart_data, $cart_item ) {
    if ( isset($cart_item['engraving']) ) {
        $cart_data[] = array( 
            "name" => __("Engraving text", "woocommerce"),  
            "value" => $cart_item['engraving'] 
        );
    }

    return $cart_data;
}

Code goes in functions.php file of the active child theme (or active theme).代码进入活动子主题(或活动主题)的functions.php文件。 Tested and works.测试和工作。


Notes:笔记:

  • This code works on the fly as it is, but it's recommended to enqueue the jQuery code as an external file.此代码按原样即时运行,但建议将 jQuery 代码作为外部文件排队。

  • On some themes you should replace:在某些主题上,您应该替换:
    $('.content-area').before(response); with $('.products').before(response);$('.products').before(response);
    to display the notices correctly…正确显示通知...

Thanks for the helpful snippet, but the above code was not working for guest uses, but only for logins.感谢您提供有用的代码段,但上面的代码不适用于访客使用,而仅适用于登录。 The wc_fragment_refresh does not trigger when you log out And use it as a guest user. wc_fragment_refresh 在您注销时不会触发并将其用作来宾用户。

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

Regards问候

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 WooCommerce AJAX 添加到购物车 - 仅限简单产品 - WooCommerce AJAX add to cart - simple products only WooCommerce AJAX放入购物车以获取可变产品,仍重定向到产品页面 - WooCommerce AJAX Add to Cart for Variable products, still redirecting to product page 隐藏WooCommerce变量产品上的“添加到购物车”按钮 - Hiding 'Add to Cart' button on WooCommerce variable products 添加到购物车并重定向到 WooCommerce 中可变产品的结帐 - Add to cart and redirect to checkout for variable products in WooCommerce Woocommerce可变产品未添加到购物车 - Woocommerce Variable Products not adding to the Cart WooCommerce 添加<custom>产品到购物车</custom> - WooCommerce Add <custom> products to cart 在Woocommerce商店页面中更改用于简单产品的购物车按钮 - Change add-to-cart button for simple products in Woocommerce shop page 在 WooCommerce 简单产品的添加到购物车按钮中显示可用性 - Display availability in add to cart button for WooCommerce simple products 如何在 WooCommerce 的单页上更改特定变量产品的添加到购物车按钮文本 - How to change add to cart button text for specific variable products on single page in WooCommerce 在 Woocommerce 单个产品的“添加到购物车”下方显示特定的运输类别 - Display specific shipping class below "Add to cart" on Woocommerce single products
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM