php Woocommerce - 产品页面 - 如何在“添加到购物车”按钮上创建 AJAX?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25892871/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 18:01:52  来源:igfitidea点击:

Woocommerce - Product Page - How to create AJAX on "Add To Cart" button?

phpajaxwordpresswoocommerce

提问by Tom Luz

I want to make an "Add To Cart" button on a product page that would work with AJAX. How can I do it? When I add to cart on a product page - it refreshes the page, how can I make it work by AJAX?

我想在可以使用 AJAX 的产品页面上制作一个“添加到购物车”按钮。我该怎么做?当我在产品页面上添加到购物车时 - 它会刷新页面,我如何通过 AJAX 使其工作?

The "Add to cart" button on "Quick View" on archive works by ajax - and it's great, but how can I do the same on product page?

存档中“快速查看”上的“添加到购物车”按钮由 ajax 工作 - 这很棒,但我如何在产品页面上做同样的事情?

I want to click on "Take me Home" on the product page which would then add the product with the selected attributes to my cart by ajax and will open that cart (like when you hover onto the bag image on menu) and shakes the bag image.

我想单击产品页面上的“带我回家”,然后通过 ajax 将具有选定属性的产品添加到我的购物车中,并打开该购物车(就像当您将鼠标悬停在菜单上的袋子图像上时)并摇晃袋子图片。

回答by anatoliy_kot

We can use ajax from archive page. it's easy -

我们可以从存档页面使用ajax。这很简单 -

Remove old button which submiting form:

删除提交表单的旧按钮:

remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );

Add ajax-link from archive page to single product page:

将 ajax-link 从存档页面添加到单个产品页面:

add_action( 'woocommerce_single_product_summary', 'woocommerce_template_loop_add_to_cart', 30 );

P.S. JS Callback. For example you can show popup with links "Back to shop" and "Cart" or "Checkout"

PS JS 回调。例如,您可以显示带有“返回商店”和“购物车”或“结帐”链接的弹出窗口

$('body').on('added_to_cart',function(){
    // Callback -> product added
    //$('.popup').show();
});

回答by Menno Evertzen

Please start by reading this page:

请先阅读此页面:

http://codex.wordpress.org/Plugin_API/Action_Reference/wp_ajax_(action)

http://codex.wordpress.org/Plugin_API/Action_Reference/wp_ajax_(action)

First you need to add some code to your functions.php for example:

首先你需要在你的functions.php中添加一些代码,例如:

add_action( 'wp_ajax_add_foobar', 'prefix_ajax_add_foobar' );
add_action( 'wp_ajax_nopriv_add_foobar', 'prefix_ajax_add_foobar' );

function prefix_ajax_add_foobar() {
   $product_id  = intval( $_POST['product_id'] );
// add code the add the product to your cart
die();
}

Then you have to add some javascript code that triggers the add to cart and makes a call to the function:

然后,您必须添加一些 javascript 代码来触发添加到购物车并调用该函数:

  jQuery( ".add-to-cart" ).each(function() 
{


    var product_id = jQuery(this).attr('rel');
    var el = jQuery(this);

    el.click(function() {

            var data = {
                action: 'add_foobar',
                product_id: product_id
            };

            jQuery.post('/wp-admin/admin-ajax.php' , data, function(response) {
                if(response != 0) {
                    // do something
                } else {
                    // do something else
                }

            });


        return false;

    });

});

This is just an example of how it can be done. Although its very basic. This javascript checks for links with the classname .add-to-cart and checks the rel attribute for the corresponding product. It then sends the product id to the php class. There you need to add code to add the corresponding product to the cart.

这只是如何做到这一点的一个例子。虽然它非常基础。这个 javascript 检查类名 .a​​dd-to-cart 的链接,并检查相应产品的 rel 属性。然后它将产品 id 发送到 php 类。在那里您需要添加代码以将相应的产品添加到购物车。

I suggest you search some more about the topic to make it suit your needs. Good luck.

我建议您搜索有关该主题的更多信息,以使其适合您的需求。祝你好运。

回答by gregbast1994

Woocommerce has come along way. I think the solution is quite easy now. In case I am missing something, all that is required it checking the "Enable AJAX add to cart buttons on archives" and using the woocommerce_template_loop_add_to_cart()function.

Woocommerce 已经出现了。我认为现在解决方案很简单。如果我遗漏了一些东西,只需检查“启用 AJAX 添加到存档上的购物车按钮”并使用该woocommerce_template_loop_add_to_cart()功能即可。

The checkbox option is under Woocommerce > Settings > Products > General.The checkbox option is under Woocommerce >Settings >Products >General.

复选框选项位于 Woocommerce > 设置 > 产品 > 常规下。The checkbox option is under Woocommerce >Settings >Products >General.

Then simply use woocommerce_template_loop_add_to_cart()wherever you wish to output the button.

然后只需在您希望输出按钮的地方使用woocommerce_template_loop_add_to_cart()即可。

If you are using a custom loop like I was, you need to be sure to make the product global in order for the woocommerce_template_loop_add_to_cart()to work.

如果您像我一样使用自定义循环,则需要确保将产品设为全局以woocommerce_template_loop_add_to_cart()使其正常工作。

Below is a small example of using the function:

下面是一个使用该函数的小例子:

add_shortcode( 'buy_again' , 'msp_buy_again_shortcode' );
function msp_buy_again_shortcode(){
    $order_items = msp_get_customer_unique_order_items( get_current_user_id() );
    echo '<div class="owl-carousel owl-theme">';
    foreach( $order_items as $id ){
        $product = wc_get_product( $id );
        global $product;

        if( ! empty( $product ) ){
            ?>
            <div class="card buy-again-product">
                <a class="link-normal" href="<?php echo $product->get_permalink(); ?>">
                    <?php echo $product->get_image( 'woocommerce_thumbnail', array( 'class' => 'card-img-top' ) ) ?>
                    <div class="card-body">
                        <?php echo wc_get_rating_html( $product->get_average_rating(), $product->get_review_count() ) ?>
                        <h5><?php echo $product->get_name(); ?></h5>
                        <p><?php echo $product->get_price_html() ?></p>
                        <?php woocommerce_template_loop_add_to_cart(); ?>
                    </div>
                </a>
            </div>
            <?php
        }
    }
    // loop and display buy again.
    // try to use the official woocommerce loop.

    echo '</div>';

}

回答by RwkY

info: Tested with WooCommerce 2.4.10.

信息:使用 WooCommerce 2.4.10 测试。

Hmm, well I did it in another way, used the woocommerce loop from add to cart (woocommerce/templates/loop/add-to-cart.php)

嗯,我用另一种方式做到了,使用了从添加到购物车的 woocommerce 循环(woocommerce/templates/loop/add-to-cart.php)

  global $product;

echo apply_filters( 'woocommerce_loop_add_to_cart_link',
    sprintf( '<a href="%s" rel="nofollow" data-product_id="%s" data-product_sku="%s" data-quantity="%s" class="button %s product_type_%s">%s</a>',
        esc_url( $product->add_to_cart_url() ),
        esc_attr( $product->id ),
        esc_attr( $product->get_sku() ),
        esc_attr( isset( $quantity ) ? $quantity : 1 ),
        $product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
        esc_attr( $product->product_type ),
        esc_html( $product->add_to_cart_text() )
    ),
$product );

BUTthe problem was that it was adding just 1 quantity, in fact, you can see in the code that is listed quantity : 1, so I had problems, until I bumped into this guys who saved me

问题是它只添加了 1 个数量,事实上,您可以在列出数量的代码中看到:1,所以我遇到了问题,直到我遇到了救我的人

ps. leaving the 1st part where it adds just 1 product for people who don't need more than 1 product in the basket, but I added a solution for those who need more than just 1 product added to the cart.

附:留下第一部分,它只为购物车中不需要超过 1 个产品的人添加 1 个产品,但我为那些需要将超过 1 个产品添加到购物车的人添加了一个解决方案。

回答by vee

Copy this code into your file. For example: my-theme-wc-single-ajax-add-cart.js.

将此代码复制到您的文件中。例如:my-theme-wc-single-ajax-add-cart.js

function myThemeWc_SingleProductAddToCart(thisObj) {
    if (typeof($) === 'undefined') {
        var $ = jQuery.noConflict();
    }

    var thisForm = thisObj.closest('form');
    var button = thisForm.find('.button');
    var formUrl = thisForm.attr('action');
    var formMethod = thisForm.attr('method');
    if (typeof(formMethod) === 'undefined' || formMethod == '') {
        formMethod = 'POST';
    }
    var formData = new FormData(thisForm[0]);
    formData.append(button.attr('name'), button.val());

    button.removeClass('added');
    button.addClass('loading');

    myThemeWc_SingleProductCartAjaxTask = $.ajax({
        url: formUrl,
        method: formMethod,
        data: formData,
        cache: false,
        contentType: false,
        processData: false
    })
    .done(function(data, textStatus, jqXHR) {
        $(document.body).trigger('wc_fragment_refresh');

        $.when(myThemeWc_SingleProductCartAjaxTask)
        .then(myThemeWc_SingleProductUpdateCartWidget)
        .done(function() {
            button.removeClass('loading');
            button.addClass('added');
            setTimeout(function() {
                button.removeClass('added');
            }, 2000);
        });
    })
    .fail(function(jqXHR, textStatus, errorThrown) {
        button.removeClass('loading');
    })
    .always(function(jqXHR, textStatus, errorThrown) {
        $('.cart').off('submit');
        myThemeWc_SingleProductListenAddToCart();
    });
}// myThemeWc_SingleProductAddToCart


function myThemeWc_SingleProductListenAddToCart() {
    if (typeof($) === 'undefined') {
        var $ = jQuery.noConflict();
    }

    $('.cart').on('submit', function(e) {
        e.preventDefault();
        myThemeWc_SingleProductAddToCart($(this));
    });
}// myThemeWc_SingleProductListenAddToCart


/**
 * Update WooCommerce cart widget by called the trigger and listen to the event.
 * 
 * @returns {undefined}
 */
function myThemeWc_SingleProductUpdateCartWidget() {
    if (typeof($) === 'undefined') {
        var $ = jQuery.noConflict();
    }

    var deferred = $.Deferred();

    $(document.body).on('wc_fragments_refreshed', function() {
        deferred.resolve();
    });

    return deferred.promise();
}// myThemeWc_SingleProductUpdateCartWidget


var myThemeWc_SingleProductCartAjaxTask;


// on page load --------------------------------------------
jQuery(function($) {
    $(document.body).on('wc_fragments_refreshed', function() {
        console.log('woocommerce event fired: wc_fragments_refreshed');
    });

    myThemeWc_SingleProductListenAddToCart();
});

You may need to replace function, variable prefix myThemeWc_to what you want.

您可能需要将函数、变量前缀替换myThemeWc_为您想要的。

This code use the original WooCommerce single product page add to cart button but stop its functional and then use ajax instead by remain all the values in the form.

此代码使用原始的 WooCommerce 单个产品页面添加到购物车按钮但停止其功能,然后使用 ajax 代替保留表单中的所有值。

Then enqueue this js file.

然后将这个js文件入队。

add_action('wp_enqueue_scripts', 'mythemewc_enqueue_scripts');
function mythemewc_enqueue_scripts() {
    if (class_exists('\WooCommerce') && is_product()) {
        wp_enqueue_script('mythemewc-single-product', trailingslashit(get_stylesheet_directory_uri()) . 'assets/js/my-theme-wc-single-ajax-add-cart.js', ['jquery'], false, true);
    }
}

You may have to code your css button to make it show the loading, added icon.
Here is css.

您可能需要对 css 按钮进行编码以使其显示加载的添加图标。
这里是css。

.woocommerce #respond input#submit.added::after, 
.woocommerce a.btn.added::after, 
.woocommerce button.btn.added::after, 
.woocommerce input.btn.added::after,
.woocommerce .single_add_to_cart_button.added::after {
    font-family: WooCommerce;
    content: '\e017';
    margin-left: .53em;
    vertical-align: bottom;
}
.woocommerce #respond input#submit.loading, 
.woocommerce a.btn.loading, 
.woocommerce button.btn.loading, 
.woocommerce input.btn.loading,
.woocommerce .single_add_to_cart_button.loading {
    opacity: .25;
    padding-right: 2.618em;
    position: relative;
}
.woocommerce #respond input#submit.loading::after, 
.woocommerce a.btn.loading::after, 
.woocommerce button.btn.loading::after, 
.woocommerce input.btn.loading::after,
.woocommerce .single_add_to_cart_button.loading::after {
    font-family: WooCommerce;
    content: '\e01c';
    vertical-align: top;
    font-weight: 400;
    position: absolute;
    right: 1em;
    -webkit-animation: spin 2s linear infinite;
    animation: spin 2s linear infinite;
}

回答by Juan Francisco

You can replicate the behavour of the archives button in your single products

您可以在单个产品中复制存档按钮的行为

add_action('wp_ajax_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart');
add_action('wp_ajax_nopriv_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart');      function woocommerce_ajax_add_to_cart() {
            $product_id = apply_filters('woocommerce_add_to_cart_product_id', absint($_POST['product_id']));
            $quantity = empty($_POST['quantity']) ? 1 : wc_stock_amount($_POST['quantity']);
            $variation_id = absint($_POST['variation_id']);
            $passed_validation = apply_filters('woocommerce_add_to_cart_validation', true, $product_id, $quantity);
            $product_status = get_post_status($product_id);

            if ($passed_validation && WC()->cart->add_to_cart($product_id, $quantity, $variation_id) && 'publish' === $product_status) {

                do_action('woocommerce_ajax_added_to_cart', $product_id);

                if ('yes' === get_option('woocommerce_cart_redirect_after_add')) {
                    wc_add_to_cart_message(array($product_id => $quantity), true);
                }

                WC_AJAX :: get_refreshed_fragments();
            } else {

                $data = array(
                    'error' => true,
                    'product_url' => apply_filters('woocommerce_cart_redirect_after_error', get_permalink($product_id), $product_id));

                echo wp_send_json($data);
            }

            wp_die();
        }
add_action('wp_ajax_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart');
add_action('wp_ajax_nopriv_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart');

function woocommerce_ajax_add_to_cart() {

            $product_id = apply_filters('woocommerce_add_to_cart_product_id', absint($_POST['product_id']));
            $quantity = empty($_POST['quantity']) ? 1 : wc_stock_amount($_POST['quantity']);
            $variation_id = absint($_POST['variation_id']);
            $passed_validation = apply_filters('woocommerce_add_to_cart_validation', true, $product_id, $quantity);
            $product_status = get_post_status($product_id);

            if ($passed_validation && WC()->cart->add_to_cart($product_id, $quantity, $variation_id) && 'publish' === $product_status) {

                do_action('woocommerce_ajax_added_to_cart', $product_id);

                if ('yes' === get_option('woocommerce_cart_redirect_after_add')) {
                    wc_add_to_cart_message(array($product_id => $quantity), true);
                }

                WC_AJAX :: get_refreshed_fragments();
            } else {

                $data = array(
                    'error' => true,
                    'product_url' => apply_filters('woocommerce_cart_redirect_after_error', get_permalink($product_id), $product_id));

                echo wp_send_json($data);
            }

            wp_die();
        }

you can see the full tutorial here

你可以在这里看到完整的教程

https://quadmenu.com/add-to-cart-with-woocommerce-and-ajax-step-by-step/

https://quadmenu.com/add-to-cart-with-woocommerce-and-ajax-step-by-step/

回答by Bhagyavant

add-to-cart.js

添加到购物车.js

jQuery( document ).on( 'click', '.product_type_simple', function() { 

var post_id = jQuery(this).data('product_id');//store product id in post id variable
var qty = jQuery(this).data('quantity');//store quantity in qty variable

jQuery.ajax({
    url : addtocart.ajax_url, //ajax object of localization
    type : 'post', //post method to access data
    data : 
    {
        action : 'prefix_ajax_add_foobar', //action on prefix_ajax_add_foobar function
        post_id : post_id,
        quantity: qty
    },

    success : function(response){

            jQuery('.site-header .quantity').html(response.qty);//get quantity
            jQuery('.site-header .total').html(response.total);//get total

            //loaderContainer.remove();
            alert("Product Added successfully..");        
    }

});

return false;
});

回答by José Jefferson

To make ajax woocomerce work on another page you will need. goes in functions.php

要使 ajax woocomerce 在另一个页面上工作,您将需要。进入functions.php

paste this:

粘贴这个:

remove_action ('woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30);

add_action ('woocommerce_single_product_summary', 'woocommerce_template_loop_add_to_cart', 30);

in footer.php in the end paste this:

在footer.php最后粘贴这个:

<script>
$ ('body'). on ('add_to_cart', function () {
???? // Callback -> product added
???? // $ ('. popup'). show ();
});
</script>

回答by Alecu Marian Alexandru

I used this plugin for the backend part https://wordpress.org/plugins/woo-ajax-add-to-cart/

我在后端部分使用了这个插件https://wordpress.org/plugins/woo-ajax-add-to-cart/

I'm not using the product page, so I modified the script to work with any button:

我没有使用产品页面,所以我修改了脚本以使用任何按钮:

(function($) {
    $(document).on('click', '.btn', function(e) {
        var $thisbutton = $(this);

        try {
            var href = $thisbutton.prop('href').split('?')[1];

            if (href.indexOf('add-to-cart') === -1) return;
        } catch (err) {
            return;
        }

        e.preventDefault();

        var product_id = href.split('=')[1];

        var data = {
            product_id: product_id
        };

        $(document.body).trigger('adding_to_cart', [$thisbutton, data]);

        $.ajax({
            type: 'post',
            url: wc_add_to_cart_params.wc_ajax_url.replace(
                '%%endpoint%%',
                'add_to_cart'
            ),
            data: data,
            beforeSend: function(response) {
                $thisbutton.removeClass('added').addClass('loading');
            },
            complete: function(response) {
                $thisbutton.addClass('added').removeClass('loading');
            },
            success: function(response) {
                if (response.error & response.product_url) {
                    window.location = response.product_url;
                    return;
                } else {
                    $(document.body).trigger('added_to_cart', [
                        response.fragments,
                        response.cart_hash
                    ]);

                    $('a[data-notification-link="cart-overview"]').click();
                }
            }
        });

        return false;
    });
})(jQuery);

回答by Eh Jewel

Just add the following attributes to the Add to Cart button to enable Ajax button.

只需将以下属性添加到“添加到购物车”按钮即可启用 Ajax 按钮。

<a href="<?php echo $product->add_to_cart_url() ?>" value="<?php echo esc_attr( $product->get_id() ); ?>" class="ajax_add_to_cart add_to_cart_button" data-product_id="<?php echo get_the_ID(); ?>" data-product_sku="<?php echo esc_attr($sku) ?>" aria-label="Add “<?php the_title_attribute() ?>” to your cart"> Add to Cart </a>

The ajax_add_to_cart add_to_cart_buttonclasses, and data-product_id="<?php echo get_the_ID(); ?>" data-product_sku="<?php echo esc_attr($sku) ?>"attributes are required.

ajax_add_to_cart add_to_cart_button类和data-product_id="<?php echo get_the_ID(); ?>" data-product_sku="<?php echo esc_attr($sku) ?>"属性是必需的。

No need to apply any action or filter.

无需应用任何操作或过滤器。