[Magento 2] Récupérer la placeholder image de votre store dans un block PHP

Objectif:

Dans la fonction suivante, je souhaite rajouter en else la possibilité d’afficher la placeholder image rendue disponible par Magento 2 si l’utilisateur admin backoffice n’a pas uploadé d’image spécifique.

Solution:

Tout d’abord, juste après la déclaration class myClassName extends…, déclarer le Helper Image et sa variable $imageHelper:

NOTE: dans mon cas (un peu particulier), une protected function _construct(): void existe déjà dans le block. Il ne faut pas chercher à la modifier!

Au lieu de ça, dans notre code et juste en-dessous ce premier contructeur, on crée une nouvelle extension de public function __construct sur le modèle de la fonction _construct tout droit issue de vendor/magento/framework/View/Element/Template.php et on y ajoute le image helper:

NOTE: \Template\Context $context devient \Magento\Framework\View\Element\Template\Context $context pour l’occasion.

Puis compléter la fonction de départ avec un else qui retourne l’image placeholder:

Cette manip’ donnera le même résultat que si on mettait en place le code suivant la le fichier template PHTML chargé d’afficher les images ou, à défaut, le placeholder. On est cependant plus efficace en renvoyant directement l’image adéquate via le block PHP. Donc, le code ci-dessous est présent juste à titre informatif mais éviter de l’utiliser dans la mesure du possible (on voit qu’on utilise, comme argument de la condition, la même méthode empty() que dans le block PHP):

[Magento 2] i18n, bonnes pratiques

Insérer un ou plusieurs liens dans une même chaîne de caractères:

(Exemple pour dans un fichier PHTML)

Insérer un mail:

(Exemple pour dans un fichier PHTML)

[jQuery] Eviter la duplication d’éléments du DOM lorsqu’on utilise .each() en exploitant correctement l’objet $(this)

Dans mon exemple, j’ai trois containers <div class="payment-method" /> qui sont présents dans le DOM. Chacun de ces containers possède son propre bouton. Je cherche à ajouter un seul nouveau bouton dans chaque container qui n’est pas tout-à-fait un clone de celui qui existe déjà, mais qui en reprend le code HTML enfant.

Problème: avec le code ci-dessous, les trois boutons que j’ajoute sont créés une fois dans chaque container. En d’autres termes, je me retrouve avec quatre boutons (au lieu de deux) dans chaque container.

Solution: le souci provient d’une mauvaise utilisation de $(this) en combinaison de .each(). Ci-dessous le code qui me donne le résultat attendu:

[Magento 2] Exploiter l’Escaper dans les fichiers PHTML et HTML utilisant Knockout JS (extension Page Builder) pour maintenir certaines balises dans du contenu HTML

Escaper dans les templates PHTML

Magento 2 supprime de manière radicale toutes les balises HTML que vous pourriez renseigner dans des champs du BO. Dans notre exemple, le champ à renseigner affiche un titre en front et si on renseigne ceci: 50<sup>th</sup> Anniversary, l’élément <sup> est automatiquement supprimé.

Pour éviter ceci, on peut déclarer(1) et exploiter l’Escaper dans les fichiers PHTML en listant dans un tableau(2) l’ensemble des balises HTML à conserver:

Valable également en cas d’utilisation d’une clé de traduction (fichiers CSV):

Extension Page Builder de Magento 2 (payante)

Documentation officielle du Page Builder Adobe Commerce (ex Magento 2).

Knockout JS dans les fichiers HTML

C’est en fait dans un fichier title-tag-escaper.js qu’on liste les tags HTML à ne pas échapper:

Configuration d’un module dans un fichier XML

Dans app/code/MyVendor/PageBuilder/view/adminhtml/pagebuilder/content_type/module_XX, afin que la liste des balises autorisées soit prise en compte il faut ajouter un attribut converter pour l’élément (le champ du formulaire d’édition en BO) ciblé:

[Javascript] Exécuter un événement qui se déclenche plusieurs fois de suite seulement après un certain délais en temps (un timeout)

Nouvelle méthode (tips: utilisez celle-ci)

Source: Debouncing and Throttling in JavaScript

Version PDF: Debouncing and Throttling in JavaScript


Ancienne méthode

…et en fait j’ai jamais réussi à la faire fonctionner.

Source: How to respond to a Javascript event only if it is fired once and then not fired again during some time period?, Debouncing Javascript Methods

Problème:

In my application I listen to the Google Maps API ‘bounds_changed’ event to send an ajax request to update some div on the web page depending on the new boundaries of the map:

The event ‘idle’ is fired with a high frequency when the user drag the map around. So much that there are too many ajax requests sent to the server.

Basically I would like to make the function to be executed only after the user has stopped to move the map during some time period (for example 500ms).

Solution

A l’addListener pour l’événement idle de l’API Google Maps, on déclare une fonction qui contiendra juste notre appel à la fonction debounce:

[Javascript] Utiliser l’API de Géolocalisation avec des promesses ou Async Await

Source: un billet clair, concis et efficace: How to use Geolocation API with Promises

Avec une promesse:

Avec async, await:

[Javascript] Eviter qu’une callback function possédant un paramètre et invoquée via un EventListener click ne s’exécute immédiatement

(comprendre: sans que l’utilisateur n’ait cliqué au préalable).

J’ai rencontré ce souci en cherchant à ajouter un addEventListener 'click' à des markers que je créais dans ma fonction pour les placer sur une Google Maps.

Avec la déclaration suivante, la fonction invoquée ci-dessous en clickCallback était exécutée immédiatement:

Pour pallier à mon problème, j’ai dû déclarer mon événement comme suit:

Le code complet pour une vision plus globale:

La fonction dans laquelle j’initialise mon eventListener:

L’exécution de cette fonction:

La callback function:

[Javascript][Google Maps v3] Eviter une boucle infinie en exécutant un événement seulement si il n’a pas été invoqué dans les dernières x secondes

Problème: des événements de l’API Google Maps v3 comme bounds_changed, zoom_changed, idle se déclenchent à chaque exécution de la méthode fitBounds qui permet d’ajuster automatiquement le zoom de la carte afin que celle-ci affiche l’ensemble des markers de la map.

MAIS… comme très souvent remonté (ici et par exemple), l’exécution de la méthode fitBounds, incontournable si on souhaite afficher tous les markers disponibles sur la carte dans le viewport, va très logiquement déclencher les événements code>bounds_changed, zoom_changed, idle, puisqu’elle va faire « bouger » la carte lorsqu’elle va zoomer ou dézoomer. Si votre fonction fitBounds est exécutée au délenchement d’un des événements pré-cités, vous entrez dans une boucle infinie: l’exécution de fitBounds recommence encore er encore jusqu’à faire crasher le navigateur.

Solution: faire un mix de ce qui est suggéré ici: Do not fire ‘zoom_changed’ event when calling fitBounds function on map et ici: Fire javascript function 2 sec after no activity in input tag.

Créer un flag qui n’autorise pas les événements de la map à être exécutés si il est assigné (comme par défaut) à false.

Mettre en place un premier timer avec un seuil de 2 secondes qui se remettra à zéro et recommencera à chronométrer à chaque fois que l’event sera déclenché. Tant que ce timer n’aura pas atteint 2 secondes, il empêchera l’événement (bounds_changed dans notre exemple) de se déclencher réellement parce que le flag restera à false. Ce qu’on cherche ici, c’est d’éviter qu’en cas de boucle, le code assigné au déclenchement de l’événement ne soit exécuté encore et encore et encore…