phpjquerywoocommerceproductproduct-variations

Woocommerce product loop - display variation select dropdown and add to cart button in archive


Trying to add a "add to cart" button within a product loop on an archive page for a variable product. Currently my loop links to the full product page to select the variation. I would like to add a drop down select for the variation options (single attribute) with an add to cart button for the chosen attribute

Currently my code below will link directly to the product page to select the variation:

<?php while ( have_posts() ): the_post(); ?>
<?php $product = wc_get_product( get_the_ID() ); /* get the WC_Product Object */ 
?>

<div class="post-item" data-id="<?php the_id(); ?>">
    <a href="<?php the_permalink(); ?>" >
        <div class="post-image"> 
            <?php echo get_the_post_thumbnail(); ?>
        </div>
        <div class="post-content">
            <h3><?php the_title(); ?></h3>
            <div class="address">
                <span class="icon-post"><img src="https://inmemoryoflife.com/wp-content/uploads/2020/07/pin-1.svg" alt=""></span><?php echo get_field('crematorium_address'); ?>
            </div>
            <div class="price">
                <span class="icon-post"><img src="https://inmemoryoflife.com/wp-content/uploads/2020/06/pound-sterling.svg" alt=""></span><?php echo $product->get_price_html(); ?>
            </div>
            <div class="button-post">
                <span>View Details</span>
            </div>
        </div>
    </a>
</div>
<?php endwhile; ?>

Solution

  • For variable products with a unique attribute for variations, you can easily add a select field for that unique attribute. Then you will be able to select the corresponding variation and add it to cart using WooCommerce Ajax add to cart functionality.

    Here is the revised code:

    <?php 
    while ( have_posts() ): the_post();
        $product = wc_get_product( get_the_ID() ); // get the WC_Product Object 
        $is_variable = $product->is_type('variable'); // Check if product is variable
        $variation_attributes = $is_variable ? $product->get_variation_attributes() : array(); // Get attributes for variations
        $attributes_count = (int) count( $variation_attributes ); // Attributes count
    ?>
    
    <div class="post-item" data-id="<?php the_id(); ?>">
        <a href="<?php the_permalink(); ?>" >
            <div class="post-image"> 
                <?php echo get_the_post_thumbnail(); ?>
            </div>
            <div class="post-content">
                <h3><?php the_title(); ?></h3>
                <div class="address">
                    <span class="icon-post"><img src="https://inmemoryoflife.com/wp-content/uploads/2020/07/pin-1.svg" alt=""></span><?php echo get_field('crematorium_address'); ?>
                </div>
                <div class="price">
                    <span class="icon-post"><img src="https://inmemoryoflife.com/wp-content/uploads/2020/06/pound-sterling.svg" alt=""></span><?php echo $product->get_price_html(); ?>
                </div>
                <?php if ( $attributes_count !== 1 ) : ?>
                <div class="button-post">
                    <span>View Details</span>
                </div>
                <?php endif; ?>
            </div>
        </a>
        <?php 
        // For variable products with only one attribute set for variations
        if ( $attributes_count === 1 ) {
            $attribute_name = current( array_keys( $variation_attributes ) );
            
            // Display the select field
            echo '<div>
            <select class="product-attribute">';
                
            printf( '<option value="">%s %s</option>', esc_html__('Select a', 'woocommerce'), wc_attribute_label( $attribute_name ) );
    
            foreach ( $product->get_available_variations( 'object ') as $variation ) {
                if ( $variation->is_in_stock() ) {
                    printf( '<option value="%s">%s</option>', $variation->get_id(), $variation->get_attribute( $attribute_name ) );
                }
            }
            echo '</select><br>';
    
            // Display the add to cart button
            printf('<a href="" data-quantity="1" class="%s" data-product_id="" rel="nofollow" data-success_message="%s">%s</a>',
                'button add_to_cart_button ajax_add_to_cart', esc_html__('The product has been added to your cart'), esc_html__('Add to cart')
            );
            echo '</div>';
        }
        ?>
    </div>
    <?php endwhile; ?>
    

    Now, some JavaScript (jQuery) code is required to add the selected variation related parameters to the add to cart button.

    The JavaScript code:

    add_action('wp_footer', 'variable_product_add_to_cart_script', 1);
    function variable_product_add_to_cart_script() {
        if ( is_woocommerce() && ! is_wc_endpoint_url() && ! is_checkout() ) :
        ?>
        <script>
        jQuery( function($) {
            $('select.product-attribute').on('change', function(){
                const productID = $(this).find(":selected").val(),
                      addToCart = $(this).parent().find('a.add_to_cart_button'),
                      hrefTag   = productID == '' ? '' : '?add-to-cart='+productID;
    
                addToCart.prop('href', hrefTag).attr('data-product_id', productID);
            });
        });
        </script>
        <?php
        endif;
    }
    

    Code goes in functions.php file of your child theme (or in a plugin).

    Tested and works with Ajax add to cart functionality enabled.