En mi tema de WooCommerce, quiero mostrar el ícono giratorio cuando WooCommerce agrega dinámicamente la clase de "carga" al elemento usando AJAX.
Traté de usar la propiedad $el de Alpine.js para recuperar el nodo DOM actual, pero esto no funciona. Tampoco está 'viendo' la classList de .
¿Cómo puedo lograr esto usando Alpine.js?
<button type="submit" name="add-to-cart" value="<?php echo esc_attr( $product->get_id() ); ?>" class="ajax_add_to_cart add_to_cart_button single_add_to_cart_button button alt flex justify-center" data-product_id="<?php echo get_the_ID(); ?>"> <!-- Spinner Icon --> <svg x-show="$el.parentElement.classList.contains('loading')" class="animate-spin py-1 h-7 w-7 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> ... </svg> <!-- Toevoegen aan winkelmand --> <span x-show="$el.parentElement.classList.contains('!loading')"> <?php echo esc_html( $product->single_add_to_cart_text() ); ?> </span> </button>Indagar en el código fuente de WooCommerce reveló que utiliza el sistema de eventos jQuery, por lo que tenemos que crear un pequeño bus de eventos entre jQuery y Alpine.js. Los dos eventos respectivos son adding_to_cart que llamó antes de la llamada AJAX y el evento added_to_cart que se activó después de la llamada AJAX exitosa (es decir, el producto se agregó al carrito).
Llamemos a nuestro bus de eventos catchWooEvents :
<script> document.addEventListener('alpine:init', () => { Alpine.data('catchWooEvents', () => ({ loading: false, init() { $(document.body).on('adding_to_cart', (event, button, data) => { this.loading = true }) $(document.body).on('added_to_cart', (fragments, cart_hash, button) => { this.loading = false }) } })) }) </script> Tenemos una nueva loading variable que está activa entre los dos eventos. Verá que usamos la $.on() de jQuery dentro de init() para capturar los eventos de jQuery, pero luego manipulamos una variable Alpine.js.
El ejemplo del botón modificado:
<div x-data="catchWooEvents"> <button type="submit" name="add-to-cart" value="<?php echo esc_attr( $product->get_id() ); ?>" class="ajax_add_to_cart add_to_cart_button single_add_to_cart_button button alt flex justify-center" data-product_id="<?php echo get_the_ID(); ?>"> <!-- Spinner Icon --> <svg x-show="loading" class="animate-spin py-1 h-7 w-7 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> ... </svg> <!-- Toevoegen aan winkelmand --> <span x-show="!loading"> <?php echo esc_html( $product->single_add_to_cart_text() ); ?> </span> </button> </div> Tenemos un nuevo elemento div principal donde aplicamos el componente catchWooEvents , por lo que varios botones secundarios pueden compartir el estado de carga. En el atributo x-show , la variable de loading ahora es reactiva.
Nota: la definición de catchWooEvents debe colocarse después de la línea de script jQuery.