Magento 2 emmits a catalog_product_compare_add_product
event whenever you add a product to the comparison list, which ultimately renders a "You added product %1 to the comparison list." message block.
How would you set up an observer in JavaScript that executes a JavaScript function whenever this event is emmitted? I'm aware you can do this by overriding \Magento\Catalog\Controller\Product\Compare\Add
, but I would prefer not doing this if there's another way that doesn't involve overriding a core controller.
UPDATE:
I noticed this code in vendor/module-catalog/view/frontend/templates/product/compare/link.phtml
:
<li class="item link compare" data-bind="scope: 'compareProducts'" data-role="compare-products-link">
<a class="action compare no-display" title="<?php /* @escapeNotVerified */ echo __('Compare Products') ?>"
data-bind="attr: {'href': compareProducts().listUrl}, css: {'no-display': !compareProducts().count}"
>
<?php /* @escapeNotVerified */ echo __('Compare Products') ?>
<span class="counter qty" data-bind="text: compareProducts().countCaption"></span>
</a>
</li>
<script type="text/x-magento-init">
{"[data-role=compare-products-link]": {"Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>}}
</script>
Since a "Compare Products n items" link will always be rendered whenever you add something to the comparison list, I guess the better question would be, how do I monitor this <li>
via KnockoutJS so that I can execute my own JavaScript whenever the link is inserted into the <li>
(without using a generic DOM mutation observer)?
UPDATE 2:
For now I have come up with a simple solution using KnockoutJS's containerless control flow that I'm somewhat satisfied with:
<li class="item link compare" data-bind="scope: 'compareProducts'" data-role="compare-products-link">
<a class="action compare no-display" title="<?php /* @escapeNotVerified */ echo __('Compare Products') ?>"
data-bind="attr: {'href': compareProducts().listUrl}, css: {'no-display': !compareProducts().count}"
>
<?php /* @escapeNotVerified */ echo __('Compare Products') ?>
(<span class="counter qty" data-bind="text: compareProducts().countCaption"></span>)
</a>
<!-- ko if: compareProducts().count -->
<script>
// Do something here when "You added product %1 to the comparison list."
// message block is displayed
</script>
<!-- /ko -->
</li>
<script type="text/x-magento-init">
{"[data-role=compare-products-link]": {"Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>}}
</script>
The reason I'm not 100% satisfied is because I have to rely on setInterval()
(and clearInterval()
to implement a timeout) to detect when the message block is displayed. If someone can come up with a solution using a true event handler in JavaScript/KnockoutJS that is only triggered when a product is added to the comparison list, then I will accept that as the answer.