1

I have created custom functionality on item form on cart page like increment/decrement qty, remove product with a custom popup, custom move to wishlist by knockout js.

For knockout events, I created custom js and initialize it on form.phtml

<div data-bind="scope: 'remove-product'" id="cart-item-table">
    <form action="<?= /* @escapeNotVerified */ $block->getUrl('checkout/cart/updatePost') ?>"
              method="post"
              id="form-validate"
              data-mage-init='{"validation":{}}'
              class="form form-cart">

              ....
              ....
    </form>
</div>

<script type="text/x-magento-init">
    {
       "*": {
            "Magento_Ui/js/core/app": {
                "components": {
                    "remove-product": {
                        "component": "Vendor_Module/js/removeproduct"
                    }
                }
            }
        }
    }
</script>

enter image description here

Now I have a third-party coupon code module which adds free gift product by applying the coupon code on cart page. For that, I just re-render item form layout on ajax response.

Everything is working fine except knockout events on item form. All knockout events stop working after re-render item form.

After some R&D, I found that we need to rebind knockout events after ajax response.

ko.applyBindings(removeproduct, $('#cart-item-table'));

It's showing error like parameter should ViewModel and element. I already defined it.

Any help would be appreciated...!

  • Same issue i face before few days. This link is helpful for me. Hope, you can get solution from this answer :) – Rohan Hapani Jan 22 at 7:01
5

We need to re-bind js component by knockout applyBindings function on ajax response.

ko.applyBindings(new removeproduct(), $('#cart-item-table')[0]);

While removeproduct is viewModel Vendor_Module/js/removeproduct and cart-item-table is the element which I need to re-bind knockout events.

1

It's better way to use data-mage-init into specific div instead of using <script type="text/x-magento-init">

x-magento-init will be call when module will be initialized. So, when module will be initialized at that time, x-magento-init script will be call. So, it will be not used for ajax response.

data-mage-init will be working same as like x-magento-init except it will call when that particular div will be load.

Example :

<div data-mage-init='{"Pulsestorm_JavascriptInitTutorial/example": {"another":"example"}}'>A single div</div>

Here, You can see on above code that when above div will be load at that time, js file will be execute. It's better way as per my view.


EDIT :

<div id="ko-example" data-bind="scope:'ko-example'">
    <!-- ko if: isVisible-->
    <div class="rh-module" data-mage-init='{"Rh_Module/js/kotemplate": {"another":"example"}}'>
        <div >A single div</div>
        <div id="rh-buttons" class="actions">
            <button type="submit" title="Select" class="action primary" id="rh-module-select-btn" data-bind="click:addCustomValue">
                <span>Select</span>
            </button>
            <button type="button" title="Cancel" class="action" id="rh-module-cancel-btn">
                <span>Cancel</span>
            </button>
        </div>
    </div>
    <!-- /ko -->
</div>

<script type="text/x-magento-init">
{
    "*": {
        "Magento_Ui/js/core/app": {
           "components": {
                "ko-example": {
                    "component": "Vendor_Module/js/kotemplate",
                    "template" : "Vendor_Module/kotemplate"
                    }
                }
            }
        }
}
</script>

Here, rh-module only visible when isVisible true and that will be get only in ajax respose. So, when <div class="rh-module"> visible kotemplate js will be call and you can bind data.

More reference

  • Thanks for the answer :). There are only difference between data-mage-init and text/x-magento-init is that data-mage-init adds js component on specific HTML element while text/x-magento-init is no relation to a certain HTML element. Both types, initialized js component on DOM ready so it's not working on ajax response. – Prince Patel Jan 22 at 8:41
  • 1
    I just found the solution to my issue. We need to re-bind the js component by knockout applyBindings function check my answer for more details. – Prince Patel Jan 22 at 9:02
  • Thanks for new solution @Prince +1 from mine. Can you please elaborate more in your answer? – Rohan Hapani Jan 22 at 9:27
  • 1
    Thanks @Rohan I will update the answer soon :) – Prince Patel Jan 22 at 9:34

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.