Bonjour.
{$product.quantity_wanted} se comporte de façon "dynamique" lorsqu'elle est dans product-details.tpl par exemple (elle se fait embarquée par l'ajax qui agit sur ce .tpl niveau id="product-details)
En remaniant un peu tous cela niveau de vos .tpl (et surement un peu de css aussi), il y'a sans doute moyen de faire ce que vous voulez.
...
Sinon si vous tenez absolument à faire votre manip de manière clean vous pourriez envisager d'en faire un module...mais là, il faut les compétences requises.
...
Solution intermédiaire (mais fastidieuse) probable que d'autres aient mieux à proposer,
Un override du ProductControler.php
(voir du coté de : public function displayAjaxRefresh() et s'inspirer de : 'product_details' => $this->render('catalog/_partials/product-details'),)
en suite s'inspirer de ce qu'on trouve dans core.js
(Sans le modifier car c'est un fichier webpack >> ou alors modif des fichiers JS qui composent core.js (qui doivent êtres dans un répertoire _dev),puis jouer du NPM pour recompiler la chose)
Donc plutôt passé par le custom.js s'inspirer de fonctions style :
var s = null, u = null; function l(e) { void 0 === e && (e = "An error occurred while processing your request"), function (e, t) { var n = (0, r.default)('<div class="alert alert-danger ajax-error" role="alert">'.concat(t, "</div>")); e.replaceWith(n) }((0, r.default)(".quickview #product-availability, .page-product:not(.modal-open) .row #product-availability, .page-product:not(.modal-open) .product-container #product-availability"), e) } function c(e, t, n) { var a = (0, r.default)(".product-actions"), c = a.find("#quantity_wanted"), f = a.find("form:first").serialize(), p = (0, i.psGetRequestParameter)("preview"); if (p = null !== p ? "&preview=" + p : "", null !== n) { if (!e || "keyup" !== e.type || c.val() !== c.data("old-value")) { c.data("old-value", c.val()), u && clearTimeout(u); var h = 30; "updatedProductQuantity" === t && (h = 750), u = setTimeout(function () { "" !== f && (s = r.default.ajax({ url: n + (-1 === n.indexOf("?") ? "?" : "&") + f + p, method: "POST", data: { quickview: (0, r.default)(".modal.quickview.in").length, ajax: 1, action: "refresh", quantity_wanted: "updatedProductCombination" === t ? c.attr("min") : c.val() }, dataType: "json", beforeSend: function () { null !== s && s.abort() }, error: function (e, t, n) { "abort" !== t && 0 === (0, r.default)("section#main > .ajax-error").length && l() }, success: function (e, n, i) { var a = (0, r.default)("<div>").append(e.product_cover_thumbnails); (0, r.default)(".quickview .images-container, .page-product:not(.modal-open) .row .images-container, .page-product:not(.modal-open) .product-container .images-container").html() !== a.find(".quickview .images-container, .page-product:not(.modal-open) .row .images-container, .page-product:not(.modal-open) .product-container .images-container").html() && (0, r.default)(".quickview .images-container, .page-product:not(.modal-open) .row .images-container, .page-product:not(.modal-open) .product-container .images-container").replaceWith(e.product_cover_thumbnails), (0, r.default)(".quickview .product-prices, .page-product:not(.modal-open) .row .product-prices, .page-product:not(.modal-open) .product-container .product-prices").first().replaceWith(e.product_prices), (0, r.default)(".quickview .product-customization, .page-product:not(.modal-open) .row .product-customization, .page-product:not(.modal-open) .product-container .product-customization").first().replaceWith(e.product_customization), (0, r.default)(".quickview .product-variants, .page-product:not(.modal-open) .row .product-variants, .page-product:not(.modal-open) .product-container .product-variants").first().replaceWith(e.product_variants), (0, r.default)(".quickview .product-discounts, .page-product:not(.modal-open) .row .product-discounts, .page-product:not(.modal-open) .product-container .product-discounts").first().replaceWith(e.product_discounts), (0, r.default)(".quickview .product-additional-info, .page-product:not(.modal-open) .row .product-additional-info, .page-product:not(.modal-open) .product-container .product-additional-info").first().replaceWith(e.product_additional_info), (0, r.default)(".quickview #product-details, #product-details").replaceWith(e.product_details), (0, r.default)(".quickview .product-flags, .page-product:not(.modal-open) .row .product-flags, .page-product:not(.modal-open) .product-container .product-flags").first().replaceWith(e.product_flags), function (e) { var t = null; (0, r.default)(e.product_add_to_cart).each(function (e, n) { if ((0, r.default)(n).hasClass("product-add-to-cart")) return t = (0, r.default)(n), !1 }), null === t && l(); var n = (0, r.default)(".product-add-to-cart"); d({ $addToCartSnippet: t, $targetParent: n, targetSelector: ".add" }), d({ $addToCartSnippet: t, $targetParent: n, targetSelector: "#product-availability" }), d({ $addToCartSnippet: t, $targetParent: n, targetSelector: ".product-minimal-quantity" }) }(e); var s = parseInt(e.product_minimal_quantity, 10); isNaN(s) || "updatedProductQuantity" === t || (c.attr("min", s), c.val(s)), o.default.emit("updatedProduct", e) }, complete: function (e, t) { s = null, u = null } })) }.bind(s, u), h) } } else l() }
Pour l'exemple je me suis amusé avec un:
(0, r.default)(".product-jetest").replaceWith(e.product_jetest)
Du coup une div class product-jetest avec du {$product.quantity_wanted} dedans, située dans un nouveau fichier.tpl que j'ai appelé product-jetest.tpl
et placé dans catalog/_partials/
Rappel : dans l'override du product controller j'ai mis un:
'product_jetest' => $this->render('catalog/_partials/product-jetest')
Donc product-jetest.tpl
(dans lequel à priori il faudrait que vous fassiez vos opérations de calcul de mètres carrés)
que j'ai fini par appeler par include dans mon fichier product.tpl
j'ai bien terminé avec un double affichage dynamique et calculable" de ma valeure input de qté avec {$product.quantity_wanted} que je peux mettre ou ca me chante dans la fiche produit (je sais pas si j'ai raté une marche mais j'ai pas eut d'erreur ni d'effets de bord)
Mais franchement je trouve que je me suis pris la tète pour pas grand chose (surtout que je suis pas à l’abri qu'un VRAIS dev passe par là et lâche une solution qui tient sur 2 lignes....)