Je me suis retrouvé dans un cas extrêmement particulier dans lequel l’utilisateur pouvait, depuis une fiche produit, rajouter des options en cascade: il pouvait en premier lieu choisir une couleur de papier cadeau (+2,00 €).

Une fois le papier cadeau sélectionné (et seulement à cette condition), il pouvait choisir d’ajouter une étiquette avec un prénom (+0,50 €).

Ce champ étiquette était limité à 14 caractères. La fonctionnalité était gérée via un widget remaining-characters.js fourni dans Magento 2.
Problème: lorsque l’utilisateur avait renseigné choisi un papier cadeau et renseigné un prénom, le prix total s’incrémentait de la somme des deux options (+2,00 € +0,50 €). Mais lorsque l’utilisateur décidait finalement de ne pas prendre de papier cadeau en décochant l’option de couleur, seul le prix du papier se décrémentait (-2,00 €) et le prix total comprenait encore celui de l’option étiquette (+0,50 €).
Solution: le plug-in qui compte le nombre de caractères présents dans le champ écoute les événements change keyup paste
:
|
_create: function () { [...] this.element.on('change keyup paste', this.updateCharacterCount.bind(this)); }, |
Lorsqu’un utilisateur décoche l’option papier cadeau, on vide l'input text
de l’option étiquette avec la méthode .val('')
, mais de cette manière le plug-in qui écoute les événements change keyup paste
n’a pas « capté » que le champ a été vidé et, de ce fait, ne remet pas le pric total à jour correctement.
Pour lui signifier que le champ a été vidé de manière dynamique, il faut chaîner notre déclaration avec la méthode .trigger()
qui contient en argument l’événement change
:
|
// Vider le champ Etiquette et reset le compteur de lettres $('.input-text', $giftWrapSticker) .val('') .trigger('change'); $('.character-counter', $giftWrapSticker).addClass('no-display'); |
Le code complet pour gérer les deux options en cascade
La deuxième contrainte était de faire fonctionner des checkboxes un peu comme des boutons radio (un seul des x checkboxes devait pouvoir être sélectionné à la fois), mais de pouvoir n’en sélectionner aucune.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
<script> require([ 'jquery' ], function ($) { // option PAPIER CADEAU + ETIQUETTE const $giftWrapOptions = $('#giftWrapOptions'), $giftWrapPrice = $('#giftWrapPrice'), $giftWrapSticker = $('#giftWrapSticker'); // On récupère le prix de la 1ère option (ttes les options ont le même prix) pour l'afficher à côté du libellé let giftWrapOptionPrice = $('.field:first-of-type .price-wrapper', $giftWrapOptions).text(); $giftWrapPrice.text(giftWrapOptionPrice); // Au clic sur l'une des options $('input[type="checkbox"]', $giftWrapOptions).on('click', function(event){ let $this = $(this); // S'assurer que seule UNE option (ou aucune) est sélectionnée if($this.hasClass('is-current-choice')){ $this.removeClass('is-current-choice'); } else { $giftWrapOptions .find('.is-current-choice') .click() .removeClass('is-current-choice'); $this.addClass('is-current-choice'); } // Afficher/masquer le champ Etiquette if($('input[type="checkbox"]', $giftWrapOptions).is(':checked')){ $giftWrapSticker.removeClass('is-hidden'); } else { $giftWrapSticker.addClass('is-hidden'); // Vider le champ Etiquette et reset le compteur de lettres $('.input-text', $giftWrapSticker) .val('') .trigger('change'); $('.character-counter', $giftWrapSticker).addClass('no-display'); } }); }); </script> |