WooCommerce Agregar varios artículos al carrito con Ajax

3 minutos de lectura

avatar de usuario
Silbido

Uso la última versión de WordPress y Woocommerce. Tengo algo de JavaScript que recorre los elementos DOM de la clase. .selectable y agarra el product_id atributo de los que tienen clase .selectedy agrega ese artículo al carrito:

// selects the elements
$('.next').on('click', function() {
    var parent  = $(this).closest('.panel');
    var selectables = parent.children('.option.selectable.selected');

    $(selectables).each(function() {
        var product = $(this).attr('product');
        add_to_cart(product, 1);    
    });
}

// add to cart AJAX
function add_to_cart(product_id, qty) {
    $.ajax({
        type: "POST",
        url: base_url + '/wp-admin/admin-ajax.php',
        data: {action : 'cl_add_to_cart', 'product_id': product_id, 'qty': qty},
        success : function(response) {
            console.log(response);
        }
    });
}

Y tengo una función de PHP en functions.php

add_action('wp_ajax_cl_add_to_cart', 'cl_add_to_cart');
add_action('wp_ajax_nopriv_cl_add_to_cart', 'cl_add_to_cart');

function cl_add_to_cart() {
    global $woocommerce;
    $product_id   = trim($_POST['product_id']);
    $qty = !empty($_POST['qty']) ? trim($_POST['qty']) : 1;
    $added = WC()->cart->add_to_cart($product_id, $qty);
    echo json_encode($added);
}

La llamada AJAX está funcionando bien en la función PHP: puedo hacer eco de $ agregado, lo que me da un hash. Si tengo dos o más elementos en la variable seleccionable, ambos presionan la función PHP (obtengo dos hashes de vuelta) pero solo el primero se agrega al carrito.

No puedo por mi vida entender por qué. ¿Algunas ideas?

  • Probé tu código y me funciona bien. ¿Está seguro de que no está agregando el mismo producto cada vez porque si está agregando el mismo producto al carrito, aumentará la cantidad de ese producto y no se considerará como un producto nuevo?

    – Bhautik

    23 de marzo de 2021 a las 4:44

avatar de usuario
LoicTheAztec

Es mejor enviar todos los elementos para que se agreguen juntos a la vez con Ajax, que enviarlos por separado en múltiples solicitudes de Ajax, esto será más ligero y efectivo.

Tienes que estar seguro de que $(selectables).each(function() { // ... }); está funcionando como esperas.

Lo siguiente enviará una solicitud Ajax única para su evento de clic.

El código jQuery

// Multi Ajax adda to cart
function multiAddToCart( productsData ) {
    $.ajax({
        url: base_url + '/wp-admin/admin-ajax.php',
        type: 'POST',
        dataType: 'JSON',
        data: {
            'action': 'multi_add_to_cart',
            'items' : Object.assign({}, productsData)
        },
        success : function(response) {
            $(document.body).trigger('wc_fragment_refresh'); // Refresh cart fragments
            console.log(response);
        },
        error : function(error) {
            console.log(error);
        }
    });
}

$('.next').on('click', function() {
    var productsData = [];
    var parent  = $(this).closest('.panel');
    var selectables = parent.children('.option.selectable.selected');

    $(selectables).each(function() {
        var productId = $(this).attr('product');
        productsData.push({'id': productId, 'qty': 1});
    });
    // Check the data before (number of items found)
    console.log(productsData); 

    multiAddToCart( productsData );
});

La función del receptor php:

add_action('wp_ajax_multi_add_to_cart', 'multi_ajax_add_to_cart');
add_action('wp_ajax_nopriv_multi_add_to_cart', 'multi_ajax_add_to_cart');
function multi_ajax_add_to_cart() {
    if (isset($_POST['items']) ) {
        $item_keys = array();

        foreach( $_POST['items'] as $item ) {
            if( isset($item['id']) ) {
                $item_qty  = isset($item['qty']) && $item['qty'] > 1 ? $item['qty'] : 1;
                $item_keys[] = WC()->cart->add_to_cart($item['id'], $item_qty);
            }
        }
        echo json_encode($item_keys); // Send back cart item keys
    }
    die();
}

El código va en el archivo functions.php del tema secundario activo (o tema activo). Probado y funciona.

Debería funcionar agregando todos los elementos a la vez.

  • OK gracias. La diferencia es que hay varios botones siguientes, como 8, por lo que tendré que abstraer productsData fuera del evento de clic para que persista.

    – hacer ping

    23 de marzo de 2021 a las 16:39

  • @Ping Con el código proporcionado es difícil adivinar todo… Entonces, ¿funciona? … Si esta respuesta responde a su pregunta, puede aceptar la respuesta y, si lo desea, también puede votar a favor de la respuesta, gracias.

    – LoicTheAztec

    23 de marzo de 2021 a las 16:45


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad