2

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.

2
  • using a plugin or event observer is not "overriding a core controller" , you can go with that approch Dec 1, 2016 at 5:01
  • @VishwasBhatnagar thanks, but is there a solution using just KnockoutJS? I just updated my question.
    – thdoan
    Dec 1, 2016 at 7:26

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.