Magento – Magento 2 – Load knockout content in modal popup

knockoutmagento2modal-popup

I want to load knockout content in modal popup on the cart page.

And to be able to bind button/click events.

Best Answer

Yeah, this was hard to figure out. I could not find any example of this in Magento docs.

I wanted to be able to bind button/click events and data to the popup, so I could call methods in my component based on user input in those popups.

Just putting a click bind on the model dom did not fire as when Magento model copies the content it does not have knockout bindings applied!

First your js needs to define the appropriate things like Magento_UI/js/modal/modal

        onRenderComplete: function () {
            var viewModel = this;
            var popupOptions = {
                type: 'popup',
                responsive: true,
                innerScroll: true,
                modalClass: 'my-popup',
                title: '<b>Save Thing</b>',
                'buttons': [{
                    text: 'Cancel',
                    class: 'action'
                }],
                opened: function () {
                    // Because magento modal copies the dom... we need to apply bindings. But it only copies once. So we want to only apply the bindings on first open.
                    if (this.appliedBindings === undefined) {
                        ko.applyBindings(viewModel, this);
                        this.appliedBindings = true;
                    }
                }
            };

In our content.html we want to add a popup such as.

<div data-bind="afterRender:onRenderComplete" class="component-wrapper">
    <button data-bind="click: showMyPopup">Show My Popup</button>

    <div id="popup-mything" class="popup-modal" style="display:none;">
        <div class="label">Blah.</div>
        <input class="mything-name" data-bind="value: myName" type="text" required placeholder="Enter name">
        <button data-bind="click: doSomething, enable: name().length > 0">Do Something</button>
    </div>
</div>

There is probably a proper way to do this, it feels like a hack but hey I've spent way too long on this.

I did find some examples/discussion which could be handy but seemed way complex/verbose...

Doing it on separate records. https://jsfiddle.net/BitWiseGuy/4u5egybp/

https://stackoverflow.com/questions/10626780/knockout-js-deferred-databinding-for-modal

Yes I could have used bootstrap but I figured magento already has a way to do it.