[Magento 2] Structure d’un plugin jQuery qui n’est ni un module RequireJS, ni un widget

app/design/frontend/MyVendor/default/Vendor_Catalog/web/js/collection-slider.js

Note: ce plugin utilise un autre plugin jQuery, à savoir Sly.

Exemple avec des paramètres:

app/design/frontend/MyVendor/default/Vendor_Catalog/requirejs-config.js

Importance de shim pour déclarer les différentes dépendances du plugin.

app/code/Vendor/Catalog/view/frontend/templates/category/whatever.phtml

Ici, veiller à bien re-lister toutes les dépendances à votre plugin (jQuery, sly, …)!

Exemple avec des paramètres:

[Magento 2] Panier abandonné template d’email transactionnel notification module Amasty Abandoned Cart Email

Documentation officielle: Magento 2 Amasty Abandoned Cart Email.

Template de la notification

Surcharge dans: app/design/frontend/MyVendor/default/Amasty_Acart/email/template.html

Envoyer un mail de test

Se rendre dans Stores > Settings > Configuration.
Puis dans Amasty Extensions > Abandoned Cart Email.

Dans la section Testing, passer le champ Safe Mode à Enabled et renseigner votre mail de test.

Puis, se rendre dans Marketing > Abandoned Cart Email > Campaigns > Test pour s’envoyer un mail de test.

[jQuery] Tester si l’utilisateur a scroll jusqu’au bas de la page footer

Source: Check if a user has scrolled to the bottom (not just the window, but any element)

Tester si l’utilisateur a atteint le bas de page

Demo

Tester si l’utilisateur est proche du bas de page

Demo

[Magento 2] Manipuler les cookies

Deux façons de manipuler des cookies dans Magento 2, en fonction de la nature de votre fichier JS:

Dans un module requireJS:

Récupère la valeur du cookie (et la teste):

Affecte une valeur à un cookie:

Sans utiliser requireJS

Structure du module:

Manipulation d’un cookie:

Le module possède sa propre fonction « faite-maison » pour lire le cookie:

De la même manière, pour créer un cookie:

[Magento 2] Résolution de l’erreur « Item with the same ID already exists »

Testé fonctionnel Magento 2.4.5. – Télécharger la source.

Source: Magento 2: How to resolve Item with the same ID “ID” already exists error?

Autres pistes: firebearstudio.com – How to fix Magento 2 item with the same ID already exists error


Créer un nouveau dossier RSCoder/DuplicateEntry dans app/code.

registration.php

etc/module.xml

etc/di.xml

plugin/Collection.php

En ligne de commande

[Magento 2] Un widget pour améliorer les performances d’affichage des produits dans les modules du pagebuilder dans l’admin

  • app/code/Vendor/PageBuilder/view/adminhtml/web/js/content-type/preview-mixin.js
  • app/code/Vendor/PageBuilder/view/adminhtml/web/js/utils/prod-all.js
  • app/code/Vendor/PageBuilder/view/adminhtml/web/js/utils/prod-delayed-loading.js
  • app/code/Vendor/PageBuilder/view/adminhtml/web/js/content-type/module-13/preview.js
  • app/code/Vendor/PageBuilder/view/adminhtml/web/js/content-type/module-13-item/preview.js
  • app/code/Vendor/PageBuilder/view/adminhtml/web/template/content-type/module-13-item/default/preview.html
  • app/code/Vendor/PageBuilder/view/frontend/templates/widget/product/simple.phtml
  • app/code/Vendor/PageBuilder/view/adminhtml/web/js/resource/vendor/sly.js (Librairie 3-rd party Sly v1.6.1)

app/code/Vendor/PageBuilder/view/adminhtml/web/template/content-type/module-13-item/default/preview.html

app/code/Vendor/PageBuilder/view/adminhtml/web/js/content-type/preview-mixin.js

Pour l’ajout de notre widget Vendor_PageBuilder/js/utils/prod-delayed-loading en tant que composant:

…et en toute fin de fichier, l’initialisation du composant:

app/code/Vendor/PageBuilder/view/adminhtml/web/js/utils/prod-all.js

Un module façon requireJS pour stocker des fonctions amenées à être utilisées dans plusieurs fichiers:

app/code/Vendor/PageBuilder/view/adminhtml/web/js/utils/prod-delayed-loading.js

Dans ce module, de nombreuses utilisations de la variable widget qui contient, sous forme de string, les données nécessaires à l’affichage du produit:

  • La valeur de l’attribut entity correspond l’ID du produit dans le catalogue. Je la récupère via une regex dans la fonction getProductId consignée dans le fichier app/code/Vendor/PageBuilder/view/adminhtml/web/js/utils/prod-all.js.
  • La valeur de l’attribut template correspond à la vue dans laquelle les données vont être affichées, en front comme en admin.

app/code/Vendor/PageBuilder/view/adminhtml/web/js/content-type/module-13/preview.js

Ajout d’une fonctionnalité « Show All » dans les options du module:

Plus bas, définition de la fonction showAll (noter comment l’habituel $ de jQuery est remplacé par (0, _jquery)):

app/code/Vendor/PageBuilder/view/adminhtml/web/js/content-type/module-13-item/preview.js

Points d’intérêt pour explorer et étendre le code:

_events.on("<em><nom_du_module></em>:renderAfter", function (args) { correspond à différents événements (:renderAfter, :updateAfter, …) qui se déclenchent au chargement du module en BO.

Les objets contentType (cf. bout de code suivant) et args contiennent également pas mal d’infos exploitables.

afterObservablesUpdated: le code qui s’exécute après que l’utilisateur ait cliqué sur le bouton « Save » (j’ai par exemple ajouté l’exécution d’une fonction setProductId qui ajoute un data-attribute dans le DOM, avec pour valeur un ID de produit):

this.contentType.id me donne l’ID du produit sur lequel j’ai itéré en sauvegardant.

app/code/Vendor/PageBuilder/view/frontend/templates/widget/product/simple.phtml

[Magento 2] S’orienter dans les sources du Page Builder

La demande était d’ajouter, en front et en back, un widget existant sur plusieurs modules spécifiques du PageBuilder de Magento 2/Adobe Commerce.

Checkliste des fichiers sur lesquels passer:

Relatif au global, modifié:

  • app/design/frontend/MyVendor/default/Magento_Theme/web/js/widgets/prod-popover.js
  • app/design/frontend/MyVendor/default/MyVendor_PageBuilder/web/css/source/module/_layout.less
  • app/design/adminhtml/MyVendor/backend/MyVendor_PageBuilder/web/css/source/content-type/_layout-bo.less
  • app/design/frontend/MyVendor/default/Magento_Theme/web/css/source/widgets/_prod-popover.less
  • app/design/adminhtml/MyVendor/backend/MyVendor_PageBuilder/web/css/source/content-type/_prod-popover-bo.less

Les fichiers importants en cas de modification:

  • app/design/frontend/MyVendor/default/MyVendor_PageBuilder/web/js/content-type/module_41.js
  • app/design/frontend/MyVendor/default/MyVendor_PageBuilder/web/js/modules/ow-mod_41.js
  • app/code/MyVendor/PageBuilder/view/adminhtml/pagebuilder/content_type/module_41.xml
  • app/code/MyVendor/PageBuilder/view/adminhtml/ui_component/pagebuilder_module_41_form.xml
  • app/code/MyVendor/PageBuilder/view/adminhtml/web/template/content-type/module-41/theme-01/master.html
  • app/code/MyVendor/PageBuilder/view/adminhtml/web/template/content-type/module-41/theme-01/preview.html

Relatif au module, pas modifié:

  • app/design/frontend/MyVendor/default/MyVendor_PageBuilder/web/css/source/module/modules/_ow-mod_41.less

app/design/frontend/MyVendor/default/MyVendor_PageBuilder/web/js/content-type/module_41.js

ATTENTION: lorsque le module comporte plusieurs thèmes, il peut arriver qu’il existe des déclinaisons du fichier module_xx.js, comme par exemple module_xx–01.js, module_xx–02.js, etc… (où 01, 02, sont les numéros des thèmes). Il faut les éditer également comme indiqué ci-dessous pour initialiser notre nouveau module.

app/code/MyVendor/PageBuilder/view/adminhtml/pagebuilder/content_type/module_41.xml

ATTENTION: veiller à bien remplacer toutes les occurences de MyVendor dans MyVendor_PageBuilder/... dans tous les fichiers XML de cet exemple (module_41.xml et pagebuilder_module_41_form.xml) par le vrai nom de votre module (vous devriez le retrouver déjà utilisé dans le fichier XML en question). Sinon, la console vous remontera une erreur de compilation sur un fichier widget-directive.js:


Refused to execute script from 'http://245.mydomain.com.local/static/version1681995189/adminhtml/SomeVendor/Backend/en_US/MyVendor_PageBuilder/js/mass-converter/product/widget-directive.js' because its MIME type ('text/plain') is not executable, and strict MIME type checking is enabled.
require.js:168 

Uncaught Error: Script error for "MyVendor_PageBuilder/js/mass-converter/product/widget-directive"
https://requirejs.org/docs/errors.html#scripterror
    at makeError (require.js:168:17)
    at HTMLScriptElement.onScriptError (require.js:1738:36)

ATTENTION #2: lorsque le module fonctionne avec une base qu’on remplit ensuite avec des (sous-)items, les ajouts des bouts de code ci-dessous se font plutôt dans un fichier module_xx_item.xml que dans un fichier module_xx.xml.

app/code/MyVendor/PageBuilder/view/adminhtml/ui_component/pagebuilder_module_41_form.xml

ATTENTION: lorsque le module fonctionne avec une base qu’on remplit ensuite avec des (sous-)items, les ajouts des bouts de code ci-dessous se font plutôt dans un fichier pagebuilder_module_xx_item_form.xml que dans un fichier pagebuilder_module_xx_form.xml.

Cacher un fieldset complet pour un thème donné

ATTENTION: à la valeur de l’attribut name dans <item name="1" xsi:type="string">theme_03</item>! Il est possible qu’elle ait déjà été défini pour theme_03 plus haut dans le fichier et qu’elle soit différente de 1. Il faut que, pour un thème donné, la valeur de l’attribut name soit identique à chaque déclaration.

Exemple complet:

app/code/MyVendor/PageBuilder/view/adminhtml/web/template/content-type/module-41/theme-01/master.html

ATTENTION: un mauvais positionnement dans le template HTML peut bloquer l’enregistrement de la page en BO!

Remarque à propos de la vue pour le front

Bien que les DIVs soient déclarées dans l’ordre suivant au sein de ow-mod__img dans le template HTML:

  1. ow-prod-popover
  2. pm-responsive-image-wrapper

…il arrive que le DOM soit rendu dans l’ordre inverse en front:

app/code/MyVendor/PageBuilder/view/adminhtml/web/template/content-type/module-41/theme-01/preview.html

Remarques pour les vues front (master.html) ET admin (preview.html)

Si présence d’un CAPTION sur les images

Certains modules permettent d’afficher un bouton caption (révélant un court texte) en bas à gauche ou à droite de l’image. Lorsque cette fonctionnalité est présente, il faut essayer de placer notre code HTML relatif au popover immédiatement APRèS celui qui affiche le bouton caption. De cette manière, le bouton du popover s’affichera automatiquement en bas à gauche si le caption est paramètré pour s’afficher en bas à droite (via le code CSS ci-dessous, déjà présent dans les fichiers source app/design/frontend/MyVendor/default/Magento_Theme/web/css/source/widgets/_prod-popover.less et app/design/adminhtml/MyVendor/backend/MyVendor_PageBuilder/web/css/source/content-type/_prod-popover-bo.less).

Dans un même thème, plusieurs déclinaisons possibles du même emplacement en image, vidéo ou image/vidéo (3 déclinaisons)

Le bout de code:

…doit se répéter autant de fois qu’il y a de déclinaisons.

Exemple complet ci-dessous uniquement pour la partie front, mais la preview.html admin devra logiquement comporter autant de répétitions que le master.html front:

[Javascript] Manipuler les objets JSON, astuces et bonnes pratiques

Boucler dans un objet JSON imbriqué et retourner une liste de toutes les valeurs d’une clé spécifique

Objectif: boucler dans l’objet JSON ci-dessous et retourner une liste de toutes les valeurs de la clé example.

Ressources en ligne: