WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

What I am trying to achieve is to have one add-to-cart button that will add the selected quantity of multiple products, featured on the catalog page, into the basket.

Here is an image of what I aim to have:

example

I've found the code that outputs the existing button has the following code:

echo apply_filters(
    'woocommerce_loop_add_to_cart_link',
    sprintf('<a href="%s" rel="nofollow" data-product_id="%s" data-product_sku="%s" class="%s button product_type_%s">%s</a>',
        esc_url( $link['url'] ),
        esc_attr( $product->id ),
        esc_attr( $product->get_sku() ),
        esc_attr( $link['class'] ),
        esc_attr( $product->product_type ),
        esc_html( $link['label'] ) ),
    $product,
    $link
);

I'm aware that there could be a way to use jQuery to submit each individual form, via a loop, at once but due to my limited knowledge, I don't think I could implement it.

Alternatively, if there is a way to have a custom button that can submit multiple forms for each product and its corresponding quantity that may make things easier in the long run.

share|improve this question

Maybe the Grouped product type is for what you want.

You can create a Grouped product and then add child products to it. A grouped product (with the child products) can be added by one click.

See WooThemes docs.

Edit:

If it's not what you're looking for, try to search for submitting multiple forms with jQuery (maybe this one), and have a look at this question about AJAX add-to-cart:

Woocommerce - Add a product to cart programmatically via JS or PHP

share|improve this answer
    
Thanks, I'll take a look into that and report back. – Ashley D Apr 17 '13 at 11:09
    
Unfortunately, this has not solved my original question, as it simply provides an alternative method of listing products. If I am going wrong somewhere, let me know. – Ashley D Apr 17 '13 at 12:37
    
Sorry to hear that, updated my answer, maybe you can use one of the links. – generousdesigner Apr 18 '13 at 14:57

The following is not a solution to just insert into a regular WooCommerce catalog page. However, this would easily serve as a basis for someone trying to achieve that.

Background: I'm building an Angular/JS app to load on the archive-product page, which will handle everything including the cart until a user is ready to proceed to checkout... at which point I needed an Ajax call to dump the entire cart in one run into the "real" WooCommerce cart and crack on with checkout. I tried to be thorough and make it almost ready to work with regular WooCommerce pages but I've never written PHP before. Additionally, I'm not falling back for any non-JS users and have no individual product pages.

There are a few plugins out there that claim to do this, but I've inspected them and all "add to cart" via Ajax, one product at a time. My feeling was, this is BS and very inefficient for large numbers of items.

My solution was to extend the WC_AJAX class and add a new method to it to handle multiple products & quantities, all in one call.

I followed this excellent tutorial and implemented my own method similarly.

I extended the class as per the noted tutorial and added a method multiple_add_to_cart as below (if you don't use ChromePhp for debugging, just delete those lines):

public static function multiple_add_to_cart() {
    ob_start();
    /*
    *Decode json to a post varioable
    */
    if ($_SERVER['REQUEST_METHOD'] == 'POST' && empty($_POST)) {
        $_POST = json_decode(file_get_contents('php://input'), true);
        $products = $_POST['products'];
    } else {
        $products = $POST['products'];
    }
    $errors = false;
    $errorArr = array();
    /* for each product, json decode data & deal with it as per original add to cart function */
    foreach ($products as $product) {
        $prod = json_decode($product);
        ChromePhp::log("Prod: " . $prod->id . " - Qty: " . $prod->qty);
        $product_id        = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $prod->id ) );
        $quantity          = empty( $prod->qty ) ? 1 : wc_stock_amount( $prod->qty );
        $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );
        $product_status    = get_post_status( $product_id );

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

        ChromePhp::log("Added!");
        do_action( 'woocommerce_ajax_added_to_cart', $product_id );

        } else {
            /*
            * If product had errors add it to error array for output at end - to inspect later with js.
            */
            $errors = true;
            $object = (object) ['id' => $product_id, 'valid' => $passed_validation, 'Status' => $product_status];
            $errorArray[] = $object;
        }
    }

    if($errors) {
        ChromePhp::log("There were errors!" . $errorArray);
        wp_send_json( $errorArray );
    } else {
        // Return fragments if you like but no use to me.
        //self::get_refreshed_fragments();

        $suc = array(
            'error'  => false,
        );
        wp_send_json( $suc );
    }

    die();
}

I then call the service within Angular/JS with an Ajax call thus:

var products = [];
        var p1 = {};
        p1['id'] = '6147';
        p1['qty'] = '3';
        products.push(JSON.stringify(p1));

        var p2 = {};
        p2['id'] = '6147';
        p2['qty'] = '4';
        products.push(JSON.stringify(p2));

        var p3 = {};
        p3['id'] = '6157'; // !Doesnt exist !
        p3['qty'] = '3';
        products.push(JSON.stringify(p3));

        $http({
            method: 'POST',
            url: sitePath,
            headers: {
                'Content-type': 'application/json'
            },
            params: {
                'wc-ajax': 'multiple_add_to_cart'
            },
            data: {
                'products': products
            }
        }).then(function(response) {
            console.log(response);
            // this callback will be called asynchronously
            // when the response is available
        }, function(response) {
            console.log(response);
            // called asynchronously if an error occurs
            // or server returns response with an error status.
        });

I expect, I'll continue to add further functions to the Ajax class to handle anything else I want to communicate with WooCommerce from within my app... gimme a shout if you want a copy of the entire class.

If any PHP gurus out there can help clean up my code a bit, make it more universal, or help port this to a functioning "plugin" for use on any WooCommerce site, that would be an awesome learn for me.

share|improve this answer
    
Nice one for the edit Gabriel! I realise i have to improve on being concise! x – Cosy Jun 23 at 17:21

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.