Tableau de produits WooCommerce : le mini-panier ne se met pas à jour
Lorsque le mini-panier WooCommerce ne se met pas à jour après un clic sur « Ajouter au panier » dans un tableau de produits, il s’agit d’un problème d’affichage, pas d’un problème de panier. Le tableau affiche Produit ajouté au panier (Product added to cart!), la page du panier liste bien le produit, mais le compteur de l’en-tête, le mini-panier du thème ou le panier latéral affiche encore l’ancien état jusqu’au rechargement de la page. Le produit est dans le panier ; le panier du thème n’en a simplement pas été informé. Vous trouverez ci-dessous ce que fait le tableau lorsqu’un produit est ajouté, comment découvrir en quelques minutes pourquoi votre panier ne réagit pas, et un script de pied de page qui le met à jour et ouvre les paniers latéraux comme le font les boutons natifs de WooCommerce.
Que se passe-t-il quand un produit est ajouté depuis le tableau
Le bouton Ajouter au panier (Add to cart) du tableau utilise le point d’entrée propre à WooCommerce, le même que celui des boutons AJAX de la page boutique :
- Le navigateur envoie une requête POST à
?wc-ajax=add_to_cartavec l’ID du produit et la quantité. WooCommerce ajoute le produit et répond avec de nouveaux fragments du panier : des morceaux de HTML pour chaque élément du panier présent sur la page, identifiés par leur sélecteur CSS, ainsi qu’uncart_hash. - Le tableau affiche son message et déclenche l’événement JavaScript
woot-added-to-cartsurdocument. - Il recharge ses propres informations de panier (le panneau du panier du tableau, les compteurs sur les boutons) et déclenche
woot-woo-cart-refreshed. - Il déclenche l’événement
wc_fragment_refreshde WooCommerce, qui demande au script de fragments du panier de WooCommerce de récupérer à nouveau les fragments et de remplacer les éléments du panier sur la page.
Le bouton Ajouter la sélection (add selected) de l’en-tête de colonne ajoute tous les produits cochés en une seule requête vers admin-ajax.php, puis exécute les étapes 3 et 4.
La différence avec les boutons de la page boutique se situe à la dernière étape. Ces boutons prennent les fragments dans la réponse, remplacent directement les éléments du panier et annoncent l’achat avec l’événement standard de WooCommerce added_to_cart, qu’écoutent les extensions de panier latéral et le bloc Mini-Cart de WooCommerce. Le tableau s’appuie à la place sur wc_fragment_refresh, et cet événement ne fait quelque chose que si le script de fragments du panier (wc-cart-fragments) est présent sur la page. Les versions actuelles de WooCommerce ne chargent ce script que là où il est nécessaire, par exemple avec le widget Panier classique ; de nombreux thèmes dotés de leur propre panier d’en-tête le chargent eux-mêmes, certains non. Le mini-panier reste donc inchangé dans quatre situations :
- le panier du thème est mis à jour par les fragments, mais le script de fragments du panier n’est pas chargé sur la page du tableau ;
- le panier latéral ou le mini-panier ne réagit qu’à
added_to_cart: il s’ouvre et se met à jour après un bouton de la boutique, jamais après le tableau ; - le compteur du thème n’est pas du tout un fragment, si bien que seul un rechargement de la page le modifie ;
- un cache de page sert un HTML avec un ancien panier, de sorte que même un rechargement affiche l’ancien nombre d’articles.
Trouver la cause en cinq minutes
Ouvrez la page du tableau dans une fenêtre de navigation privée, où vous n’êtes pas connecté, puis ouvrez les outils de développement (F12, ou Cmd+Option+I sur Mac).
- Réseau. Ajoutez un produit depuis le tableau et cliquez sur la requête
?wc-ajax=add_to_cart. Si sa réponse contient"error":true, le produit n’a pas été ajouté et le problème vient du produit (stock, limites de quantité), pas du mini-panier. Sinon, développezfragments: ses clés, commediv.widget_shopping_cart_content, sont les éléments du panier que WooCommerce et votre thème peuvent rafraîchir. - Votre élément de panier. Faites un clic droit sur le compteur de l’en-tête ou sur le mini-panier, choisissez Inspecter (Inspect) et comparez sa balise et sa classe avec ces clés. Si rien ne correspond, l’élément n’est pas un fragment : voir la section sur le filtre PHP ci-dessous.
- Console. Saisissez
typeof wc_cart_fragments_paramset appuyez sur Entrée."undefined"signifie que le script de fragments du panier n’est pas sur la page ;wc_fragment_refreshne fait donc rien. - Comparer avec la boutique. Sur la page boutique, ajoutez un produit avec le bouton natif de WooCommerce. Si le mini-panier s’y met à jour ou si le panier latéral s’y ouvre, mais pas après le tableau, votre panier écoute
added_to_cart, ce que fournit le script de pied de page ci-dessous. - Recharger. Si le compteur est toujours faux après un rechargement alors que la page du panier affiche le produit, la page provient d’un cache ; voir la section sur la mise en cache.
Mettre à jour le mini-panier et ouvrir le panier latéral depuis le tableau
Ce script fait ce que font les boutons de la page boutique. Chaque fois que le panier du tableau a été rafraîchi, il récupère les fragments auprès de WooCommerce et remplace les éléments du panier sur la page, sans dépendre du script de fragments du panier. Après un clic sur Ajouter au panier (Add to cart) ou Ajouter la sélection (add selected), il déclenche aussi added_to_cart avec les vrais fragments, de sorte que les paniers latéraux et le bloc Mini-Cart se mettent à jour et s’ouvrent selon leur configuration.
/*
* Products tables: update the theme mini cart and side cart after products are
* added from a table. Add it to the site footer: a JavaScript snippet in a code
* snippets plugin, or the footer scripts field of your theme.
*/
(function ($) {
var announce = false;
function fragmentsUrl() {
if (typeof wc_add_to_cart_params !== 'undefined') {
return wc_add_to_cart_params.wc_ajax_url.toString().replace('%%endpoint%%', 'get_refreshed_fragments');
}
return '?wc-ajax=get_refreshed_fragments';
}
// One product added with a table's Add to cart button
document.addEventListener('woot-added-to-cart', function () {
announce = true;
});
// Several products added with the "add selected" button
document.addEventListener('click', function (e) {
var button = e.target.closest('.woot-add-to-cart-all-btn');
var table = button ? button.closest('table') : null;
if (table && table.querySelector('.woot-add-to-cart-check:checked')) {
announce = true;
}
}, true);
// The table cart was refreshed: on page load, after adding, removing or changing quantities
document.addEventListener('woot-woo-cart-refreshed', function () {
var opened = announce;
announce = false;
$.post(fragmentsUrl(), function (data) {
if (!data || !data.fragments) {
return;
}
$.each(data.fragments, function (selector, html) {
$(selector).replaceWith(html);
});
$(document.body).trigger('wc_fragments_refreshed');
if (opened) {
$(document.body).trigger('added_to_cart', [data.fragments, data.cart_hash, $()]);
}
});
});
})(jQuery);
Son fonctionnement :
- Les éléments du panier sont rafraîchis à chaque modification faite via le tableau, y compris les suppressions et les changements de quantité dans la fenêtre du panier du tableau. L’événement
added_to_cart, et avec lui l’ouverture d’un panier latéral, n’intervient qu’après un ajout de produits. - Le panier du tableau est également rafraîchi une fois au chargement de la page ; le script effectue donc une requête de fragments supplémentaire par page contenant un tableau. Cela garde le mini-panier exact sur les pages servies depuis un cache.
- Certains paniers latéraux ne s’ouvrent que par leur propre fonction, et non via
added_to_cart. Si le vôtre reste fermé alors que son contenu se met à jour, appelez cette fonction dans le blocif (opened); la documentation du panier latéral ou son développeur peut vous indiquer son nom.
Si vous préférez envoyer le client vers le panier, l’onglet Options du tableau propose Après l’ajout au panier (After to cart adding) avec Rediriger vers la page du panier (Redirect to the cart page) et Rediriger vers la page de paiement (Redirect to the checkout page). Le tableau peut aussi afficher son propre panier, toujours synchronisé : activez Afficher le panier de la boutique (Show shop cart) dans le même onglet, ou placez [woot_cart] n’importe où sur la page.
Quand le compteur de panier du thème n’est pas un fragment
Un compteur qui ne figure pas dans la liste fragments ne peut être rafraîchi par aucun script, car WooCommerce n’envoie jamais de nouveau HTML pour lui. Enregistrez-le avec le filtre woocommerce_add_to_cart_fragments de WooCommerce. Remplacez span.my-cart-count par la balise et la classe du compteur de votre thème, et conservez la même classe dans le HTML renvoyé afin que l’élément puisse être retrouvé la fois suivante :
/*
* Make the theme's cart counter a WooCommerce fragment, so it is refreshed
* after AJAX add to cart. Child theme functions.php or a code snippets plugin.
*/
add_filter('woocommerce_add_to_cart_fragments', function ($fragments) {
$fragments['span.my-cart-count'] = '<span class="my-cart-count">'
. esc_html(WC()->cart->get_cart_contents_count())
. '</span>';
return $fragments;
});
Cela aide autant les boutons de la page boutique que le tableau. Les thèmes et les constructeurs de pages dotés d’un mini-panier complexe l’enregistrent généralement déjà ; si le leur est absent de la liste, demandez au développeur du thème quel élément utiliser.
Mise en cache des pages et optimisation des scripts
Un cache de page stocke le HTML d’une page, panier d’en-tête compris. Si le thème imprime son panier dans le HTML et que le cache continue de servir la version générée pour un panier vide, le compteur est faux après chaque rechargement, alors que la page du panier, que les extensions de cache excluent par défaut, est correcte. Deux mesures règlent le problème, et les caches pour boutiques WooCommerce ont besoin des deux :
- Ne servez pas de pages en cache aux visiteurs dont le panier contient des articles. WooCommerce définit pour eux les cookies
woocommerce_items_in_cartetwoocommerce_cart_hash; la plupart des extensions de cache et des hébergeurs peuvent contourner le cache lorsqu’ils existent. WooCommerce indique les pages et les cookies à exclure dans Configuring caching plugins. - Ne mettez jamais en cache les requêtes
?wc-ajax=niadmin-ajax.php. Une réponse de fragments mise en cache place le même panier sur la page de chaque visiteur.
Les fonctions d’optimisation qui retardent, différent ou combinent le JavaScript peuvent aussi casser la chaîne décrite plus haut : si le script de panier du thème ou les scripts de panier de WooCommerce s’exécutent tard ou pas du tout, rien ne met le panier à jour. Excluez jQuery, les scripts add-to-cart et cart-fragments de WooCommerce, le script de panier de votre thème et le dossier /wp-content/plugins/profit-products-tables-for-woocommerce/, puis videz tous les caches. Si la désactivation de l’extension de cache ou d’optimisation (WP Rocket ou une autre) corrige le mini-panier, passez en revue ses options de cache et de JavaScript une à une pour trouver le réglage responsable, plutôt que de laisser l’extension désactivée.
Liste de contrôle
- La requête
?wc-ajax=add_to_cartrépond avecfragments, et non avec"error":true. - Le panier ou le compteur de votre en-tête correspond à l’une des clés de fragments, ou est enregistré avec
woocommerce_add_to_cart_fragments. - Le script de pied de page est présent sur la page du tableau, et la console du navigateur n’affiche aucune erreur.
- Les pages ne sont pas servies depuis le cache aux visiteurs dont le panier contient des articles ; les requêtes
wc-ajaxne sont jamais mises en cache. - Les scripts de panier de WooCommerce, le script de panier du thème et le dossier de l’extension sont exclus du retardement, du report et de la combinaison du JavaScript.
Si le panier ne se met toujours pas à jour, ouvrez un sujet sur le forum de support de WOOT en indiquant le lien de la page, le nom de votre thème ou de l’extension de panier latéral et les clés de fragments de la réponse add_to_cart, et nous examinerons le problème.