[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"theme-db":3,"$fuPUoH9l_NMmmYPLcrz83CN8-j3sxVHA82xs-luWKpzg":22,"footer-db":61,"megamenu":81,"$fKnz2vuX4bZz1LbUTiuFsvSZ3e07l5_5fqNYp4Tzdhi8":149,"$flCzauZXjAhom_yZwaUaapKuS7crZWhhbsTGn6aHIPHk":216,"header-db":230},{"theme":4},{"colors":5,"typography":13,"ui":17,"defaultColorMode":21},{"primary":6,"secondary":7,"background":8,"foreground":9,"muted":10,"headerBg":11,"footerBg":12,"topBarBg":9,"topBarText":11},"#4F46E5","#0D9488","#F9FAFB","#111827","#6B7280","#ffffff","#020617",{"fontFamily":14,"fontUrl":15,"baseFontSize":16},"Inter, system-ui, sans-serif","https:\u002F\u002Ffonts.googleapis.com\u002Fcss2?family=Inter:wght@400;500;600;700&family=Playfair+Display:ital,wght@0,400;0,700;0,800;0,900;1,400;1,700&display=swap","16px",{"borderRadius":18,"contentWidth":19,"shadow":20},"lg","7xl",true,"light",{"title":23,"slug":24,"metaDescription":25,"category":26,"tags":27,"difficulty":34,"psVersions":35,"content":39,"faq":40,"tldr":56,"readingTime":57,"generatedAt":58,"publishDate":58,"relatedArticles":59,"sourceCategory":60},"Passer une variable produit (EAN13) au panier AJAX PrestaShop","passer-variable-produit-ean13-panier-ajax-prestashop","Comment transmettre l'EAN13 ou toute variable produit au panier AJAX PrestaShop via Smarty et JavaScript. Guide technique avec code prêt à l'emploi.","developpement",[28,29,30,31,32,33],"ajax-cart","smarty","javascript","ean13","variables-produit","layer-cart","intermediaire",[36,37,38],"1.6","1.7","8.x","\u003Ch2>Le problème : rendre une donnée produit accessible côté JavaScript\u003C\u002Fh2>\n\u003Cp>Lorsqu'on personnalise le panier AJAX de PrestaShop (le fameux \"layer cart\" en 1.6, ou le modal d'ajout au panier en 1.7+), on a parfois besoin d'accéder à des données produit qui ne sont pas exposées par défaut côté JavaScript — typiquement l'EAN13, la référence fournisseur, ou tout attribut personnalisé.\u003C\u002Fp>\n\u003Cp>Le réflexe initial est souvent de tenter un \u003Ccode>{$product.ean13}\u003C\u002Fcode> directement dans un fichier JavaScript ou dans un template global. Mais cette approche se heurte à un obstacle fondamental : \u003Cstrong>le contexte Smarty d'un produit n'est disponible que dans la boucle qui itère sur les produits\u003C\u002Fstrong>.\u003C\u002Fp>\n\u003Ch2>Pourquoi ça ne fonctionne pas dans une boucle `foreach`\u003C\u002Fh2>\n\u003Cp>Si vous affichez une liste de produits (catégorie, accueil, recherche), chaque produit est rendu dans une boucle \u003Ccode>{foreach}\u003C\u002Fcode>. Si vous tentez d'injecter une variable JavaScript à l'intérieur de cette boucle avec \u003Ccode>{addJsDef}\u003C\u002Fcode>, \u003Cstrong>chaque itération écrase la précédente\u003C\u002Fstrong> : à la fin du rendu, votre variable JavaScript ne contient que la valeur du dernier produit.\u003C\u002Fp>\n\u003Cp>C'est un piège classique qui génère des bugs silencieux — le code semble fonctionner, mais la valeur est toujours celle du dernier élément de la liste.\u003C\u002Fp>\n\u003Ch2>Solution 1 : Input caché avec identifiant unique (pages listing)\u003C\u002Fh2>\n\u003Cp>Pour les pages qui affichent plusieurs produits, la méthode la plus fiable consiste à stocker la donnée dans un élément HTML avec un identifiant unique par produit :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-smarty\">\n{* Dans le template de boucle produit (product-list.tpl ou équivalent) *}\n{foreach from=$products item=product}\n  &lt;div class=\"product-container\" data-id=\"{$product.id_product}\"&gt;\n    {* ... affichage du produit ... *}\n    &lt;input type=\"hidden\" \n           id=\"ean13_{$product.id_product}\" \n           value=\"{$product.ean13|escape:'htmlall':'UTF-8'}\" \u002F&gt;\n  &lt;\u002Fdiv&gt;\n{\u002Fforeach}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Côté JavaScript, on récupère ensuite la valeur ciblée :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-javascript\">\n\u002F\u002F Récupérer l'EAN13 d'un produit spécifique par son ID\nfunction getProductEan13(productId) {\n    var input = document.getElementById('ean13_' + productId);\n    return input ? input.value : '';\n}\n\n\u002F\u002F Exemple lors de l'ajout au panier\n$('.ajax_add_to_cart_button').on('click', function () {\n    var productId = $(this).data('id-product');\n    var ean13 = getProductEan13(productId);\n    \u002F\u002F Utiliser ean13 dans votre logique personnalisée\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cstrong>Avantage :\u003C\u002Fstrong> chaque produit conserve sa propre valeur, pas d'écrasement.\u003C\u002Fp>\n\u003Ch2>Solution 2 : `addJsDefL` pour la fiche produit (page unique)\u003C\u002Fh2>\n\u003Cp>Sur la fiche produit, un seul produit est affiché. On peut donc injecter directement une variable JavaScript globale via la fonction Smarty \u003Ccode>{addJsDefL}\u003C\u002Fcode> :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-smarty\">\n{* Dans product.tpl (PrestaShop 1.6) *}\n{addJsDefL name=productEan13}{$product-&gt;ean13|escape:'javascript'}{\u002FaddJsDefL}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>La variable \u003Ccode>productEan13\u003C\u002Fcode> est alors disponible dans tous vos fichiers JavaScript :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-javascript\">\n\u002F\u002F Personnaliser l'image du layer cart avec l'EAN13\nif (typeof productEan13 !== 'undefined' && productEan13) {\n    $('.layer_cart_img').html(\n        '&lt;img class=\"layer_cart_img img-responsive\" ' +\n        'src=\"' + baseUri + 'img\u002Fcms\u002Fillustrations\u002F' + productEan13 + '.jpg\" ' +\n        'alt=\"' + productEan13 + '\" \u002F&gt;'\n    );\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Différence entre `addJsDef` et `addJsDefL`\u003C\u002Fh3>\n\u003Ctr>\u003Cth>Fonction\u003C\u002Fth>\u003Cth>Type de sortie\u003C\u002Fth>\u003Cth>Usage\u003C\u002Fth>\u003C\u002Ftr>\n\u003Ctr>\u003Cth>`{addJsDef}`\u003C\u002Fth>\u003Cth>Variable JS brute\u003C\u002Fth>\u003Cth>Nombres, booléens, objets JSON\u003C\u002Fth>\u003C\u002Ftr>\n\u003Ctr>\u003Cth>`{addJsDefL}`\u003C\u002Fth>\u003Cth>Chaîne JS échappée\u003C\u002Fth>\u003Cth>Textes, EAN, références (protège les guillemets)\u003C\u002Fth>\u003C\u002Ftr>\n\u003Cp>\u003Ccode>addJsDefL\u003C\u002Fcode> est à privilégier pour les chaînes de caractères car il gère automatiquement l'échappement, évitant les injections XSS et les erreurs de syntaxe JavaScript.\u003C\u002Fp>\n\u003Ch2>Approche moderne : PrestaShop 1.7 et 8.x\u003C\u002Fh2>\n\u003Cp>À partir de PrestaShop 1.7, l'architecture a changé. Le système de templates utilise désormais des événements JavaScript et un objet \u003Ccode>prestashop\u003C\u002Fcode> global.\u003C\u002Fp>\n\u003Ch3>Méthode via les data attributes\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-html\">\n{* Dans le template produit (themes\u002Fvotre-theme\u002Ftemplates\u002Fcatalog\u002Fproduct.tpl) *}\n&lt;div id=\"product-details\" \n     data-product=\"{$product.embedded_attributes|json_encode|escape:'htmlall':'UTF-8'}\"\n     data-ean13=\"{$product.ean13|escape:'htmlall':'UTF-8'}\"&gt;\n&lt;\u002Fdiv&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cpre>\u003Ccode class=\"language-javascript\">\n\u002F\u002F Récupération propre en JS\nconst productDetails = document.getElementById('product-details');\nconst ean13 = productDetails?.dataset.ean13 || '';\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Méthode via l'événement `updatedProduct`\u003C\u002Fh3>\n\u003Cp>En 1.7+, chaque changement de déclinaison déclenche un événement. C'est la méthode recommandée pour réagir dynamiquement :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-javascript\">\nprestashop.on('updatedProduct', function (event) {\n    if (event.product_url) {\n        \u002F\u002F Recharger les données produit si nécessaire\n        \u002F\u002F L'EAN13 peut changer selon la déclinaison\n    }\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>PrestaShop 8.x : exposer des données via un module\u003C\u002Fh3>\n\u003Cp>Pour une approche propre et maintenable en PrestaShop 8, créez un hook dans votre module :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">\n\u002F\u002F Dans votre module\npublic function hookActionFrontControllerSetMedia()\n{\n    Media::addJsDef([\n        'customProductData' =&gt; [\n            'ean13' =&gt; $this-&gt;getProductEan13(),\n        ]\n    ]);\n}\n\nprivate function getProductEan13(): string\n{\n    $idProduct = (int) Tools::getValue('id_product');\n    if (!$idProduct) {\n        return '';\n    }\n    $product = new Product($idProduct);\n    return $product-&gt;ean13 ?? '';\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>Bonnes pratiques\u003C\u002Fh2>\n\u003Col>\n\u003Cli>**Toujours échapper les valeurs** — que ce soit avec `|escape:'htmlall'` dans Smarty ou `htmlspecialchars()` en PHP. Un EAN13 semble inoffensif, mais un champ mal échappé reste un vecteur XSS.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Col>\n\u003Cli>**Vérifier l'existence de la variable** — en JavaScript, toujours tester `typeof maVariable !== 'undefined'` avant utilisation pour éviter les erreurs sur les pages où le contexte produit n'existe pas.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Col>\n\u003Cli>**Préférer les data attributes aux variables globales** — en 1.7+, les `data-*` sont plus propres que les variables globales JavaScript et facilitent le debug.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Col>\n\u003Cli>**Activer le mode debug** — en cas de page blanche après modification d'un template Smarty, activez immédiatement le mode debug PrestaShop (`_PS_MODE_DEV_` à `true` dans `config\u002Fdefines.inc.php`) pour obtenir le message d'erreur exact.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Col>\n\u003Cli>**Attention aux déclinaisons** — l'EAN13 peut varier selon la déclinaison produit. Sur une fiche produit avec déclinaisons, pensez à mettre à jour la valeur lors du changement de combinaison.\u003C\u002Fli>\n\u003C\u002Ful>",[41,44,47,50,53],{"q":42,"a":43},"Pourquoi ma variable Smarty est toujours celle du dernier produit dans une boucle foreach ?","Lorsqu'on utilise `{addJsDef}` à l'intérieur d'une boucle `{foreach}`, chaque itération écrase la variable JavaScript précédente. À la fin du rendu, seule la valeur du dernier produit subsiste. La solution est d'utiliser des inputs cachés avec un identifiant unique par produit (`id=\"ean13_{$product.id_product}\"`) ou des data attributes HTML5, puis de cibler le bon élément en JavaScript au moment de l'interaction.",{"q":45,"a":46},"Quelle est la différence entre addJsDef et addJsDefL dans PrestaShop ?","`{addJsDef}` injecte une valeur JavaScript brute — idéal pour les nombres, booléens ou objets. `{addJsDefL}` encapsule la valeur dans une chaîne JavaScript correctement échappée, ce qui protège contre les erreurs de syntaxe et les failles XSS. Pour toute donnée textuelle comme un EAN13, une référence ou un nom de produit, utilisez systématiquement `{addJsDefL}`.",{"q":48,"a":49},"Comment passer des données produit au JavaScript dans PrestaShop 8 ?","En PrestaShop 8, la méthode recommandée est d'utiliser `Media::addJsDef()` dans un hook de votre module (par exemple `hookActionFrontControllerSetMedia`). Vous pouvez aussi utiliser les data attributes HTML5 dans vos templates Twig. L'ancienne syntaxe Smarty `{addJsDef}` n'est plus utilisable car PrestaShop 8 utilise Twig comme moteur de templates pour le front-office.",{"q":51,"a":52},"Comment accéder à l'EAN13 d'une déclinaison spécifique en JavaScript ?","En PrestaShop 1.7+, écoutez l'événement `prestashop.on('updatedProduct')` qui se déclenche à chaque changement de déclinaison. L'objet événement contient les données mises à jour du produit. En 1.6, il faut intercepter l'appel AJAX de changement de combinaison et extraire l'EAN13 de la réponse, ou stocker toutes les valeurs EAN13 par déclinaison dans un objet JavaScript au chargement de la page.",{"q":54,"a":55},"Page blanche après avoir ajouté addJsDef dans un template PrestaShop, que faire ?","Une page blanche indique généralement une erreur de syntaxe Smarty. Activez le mode debug en passant `_PS_MODE_DEV_` à `true` dans `config\u002Fdefines.inc.php`. Les causes fréquentes : oubli d'accolade fermante, utilisation de `$product->ean13` (notation objet) au lieu de `$product.ean13` (notation tableau) dans le contexte du template, ou guillemets non échappés dans la valeur injectée.","Pour transmettre une variable produit (comme l'EAN13) au panier AJAX PrestaShop, utilisez des inputs cachés avec ID unique dans les boucles foreach, ou `{addJsDefL}` sur la fiche produit. En PrestaShop 8, préférez `Media::addJsDef()` dans un hook de module.",5,"2026-03-21T13:52:41.000Z",[],"PrestaShop pour les développeurs",{"footer":62},{"theme":63,"description":64,"hours":64,"logo":65,"contact":69,"social":70,"bottomBar":80},"dark",null,{"src":66,"href":67,"alt":68},"\u002Flogo-ac.svg","\u002F","Alexandre Carette",{"email":64,"phone":64,"address":64,"cta":64},[71,74,77],{"platform":72,"href":73,"label":72},"linkedin","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Falexandre-carette\u002F",{"platform":75,"href":76,"label":75},"malt","https:\u002F\u002Fwww.malt.fr\u002Fprofile\u002Falexandrecarette",{"platform":78,"href":79,"label":78},"github","https:\u002F\u002Fgithub.com\u002Fprest4cafe",{"copyright":64},{"items":82},[83,93,101,109,117,126,133,141],{"id":84,"type":85,"label":86,"href":88,"icon":64,"description":64,"badge":64,"groupTitle":64,"style":64,"gridColumns":64,"cssClass":64,"psCategoryId":64,"showPsChildren":89,"position":90,"children":91,"psChildren":92},41,"link",{"fr":87},"Expertise","\u002Fexpertise",false,0,[],[],{"id":94,"type":85,"label":95,"href":97,"icon":64,"description":64,"badge":64,"groupTitle":64,"style":64,"gridColumns":64,"cssClass":64,"psCategoryId":64,"showPsChildren":89,"position":98,"children":99,"psChildren":100},42,{"fr":96},"Blog","\u002Fblog",1,[],[],{"id":102,"type":85,"label":103,"href":105,"icon":64,"description":64,"badge":64,"groupTitle":64,"style":64,"gridColumns":64,"cssClass":64,"psCategoryId":64,"showPsChildren":89,"position":106,"children":107,"psChildren":108},43,{"fr":104},"Modules PrestaShop","\u002Fmodules",2,[],[],{"id":110,"type":85,"label":111,"href":113,"icon":64,"description":64,"badge":64,"groupTitle":64,"style":64,"gridColumns":64,"cssClass":64,"psCategoryId":64,"showPsChildren":89,"position":114,"children":115,"psChildren":116},44,{"fr":112},"Outils IA","\u002Foutils-ia",3,[],[],{"id":118,"type":85,"label":119,"href":121,"icon":64,"description":64,"badge":64,"groupTitle":64,"style":122,"gridColumns":64,"cssClass":64,"psCategoryId":64,"showPsChildren":89,"position":123,"children":124,"psChildren":125},45,{"fr":120},"Offre Starter ✨","\u002Foffre-starter",{"highlight":20},4,[],[],{"id":127,"type":85,"label":128,"href":130,"icon":64,"description":64,"badge":64,"groupTitle":64,"style":64,"gridColumns":64,"cssClass":64,"psCategoryId":64,"showPsChildren":89,"position":57,"children":131,"psChildren":132},46,{"fr":129},"Academy","\u002Facademy",[],[],{"id":134,"type":85,"label":135,"href":137,"icon":64,"description":64,"badge":64,"groupTitle":64,"style":64,"gridColumns":64,"cssClass":64,"psCategoryId":64,"showPsChildren":89,"position":138,"children":139,"psChildren":140},47,{"fr":136},"À propos","\u002Fa-propos",6,[],[],{"id":142,"type":85,"label":143,"href":145,"icon":64,"description":64,"badge":64,"groupTitle":64,"style":64,"gridColumns":64,"cssClass":64,"psCategoryId":64,"showPsChildren":89,"position":146,"children":147,"psChildren":148},48,{"fr":144},"Contact","\u002Fcontact",7,[],[],{"columns":150},[151,163,193,209],{"title":152,"links":153},"Plateforme",[154,156,159,160],{"label":155,"href":121,"external":89},"Offre Starter (2 500 €)",{"label":157,"href":158,"external":89},"Devenir Ambassadeur","\u002Fambassadeur",{"label":104,"href":105,"external":89},{"label":161,"href":162,"external":20},"CodeMyShop.com","https:\u002F\u002Fcodemyshop.com",{"title":164,"links":165},"Le Synedre",[166,169,172,175,178,181,184,187,190],{"label":167,"href":168,"external":89},"L'histoire","\u002Fsynedre",{"label":170,"href":171,"external":89},"Constitution","\u002Fsynedre\u002Fconstitution",{"label":173,"href":174,"external":89},"L'équipe","\u002Fequipe",{"label":176,"href":177,"external":89},"Le réacteur en direct","\u002Freacteur",{"label":179,"href":180,"external":89},"Le Drill (entraînement)","\u002Fdrill",{"label":182,"href":183,"external":89},"Protocole de réunion","\u002Fsynedre\u002Freunion",{"label":185,"href":186,"external":89},"Les agents IA","\u002Fagents-ia",{"label":188,"href":189,"external":89},"La Conduite","\u002Fsynedre\u002Fconduite",{"label":191,"href":192,"external":89},"Charte plateforme","\u002Fsynedre\u002Fcharte",{"title":194,"links":195},"Ressources",[196,197,198,201,203,206],{"label":96,"href":97,"external":89},{"label":129,"href":130,"external":89},{"label":199,"href":200,"external":89},"Dictionnaire","\u002Fdictionnaire",{"label":202,"href":88,"external":89},"Expertise PrestaShop",{"label":204,"href":205,"external":89},"Flywheel","\u002Fflywheel",{"label":207,"href":208,"external":89},"Manifeste","\u002Fmanifeste",{"title":136,"links":210},[211,212,215],{"label":68,"href":137,"external":89},{"label":213,"href":214,"external":89},"Dossier de presse","\u002Fpresse",{"label":144,"href":145,"external":89},{"academy":217,"blog":218,"expertise":229},[],[219,223,226],{"title":220,"url":221,"score":98,"type":222},"PrestaShop headless avec Nuxt 3 : pourquoi séparer back et front","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fprestashop-headless-nuxt-separation-front-back","blog",{"title":224,"url":225,"score":98,"type":222},"PrestaShop headless : Nuxt 3, pas Next.js — le choix souverain","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fprestashop-headless-nuxt-nextjs-souverainete",{"title":227,"url":228,"score":98,"type":222},"Sylius rachète PrestaShop : ce que ça change pour vous","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fsylius-rachat-prestashop-headless-souverainete",[],{"header":231},{"logo":232,"topBar":235,"contactEmail":238,"features":239,"navBar":64},{"src":66,"alt":233,"text":68,"href":67,"class":234},"Alexandre Carette — Architecte E-commerce Souverain","h-10 w-10",{"message":64,"showLanguages":89,"align":236,"languages":237},"left",[],"contact@alexandrecarette.fr",{"showSearch":89,"showWishlist":89,"showLogin":20,"showContact":89,"showCart":89,"stickyHeader":20,"headerLayout":240},"inline"]