4

I want to extend the module-checkout/view/frontend/web/template/shipping.html so that I can add a new custom binding to the shipping method options so that on init I can trigger another action. I have successfully loaded my shipping.html template and shipping.js files. However, I do not know how to get my customBinding.js file to be picked up by the shipping.html

I copied the module-checkout/view/frontend/web/template/shipping.html to my module MyVendor/MyModule/view/frontend/web/template/shipping.html and modified the <input name="shipping_method" type="radio"></input> button to include a new binding as follows:

File: MyVendor/MyModule/view/frontend/web/template/shipping.html

<input name="shipping_method" type="radio"
     data-bind="
         value: method.carrier_code + '_' + method.method_code,
         checked: $parent.isSelected,
         attr: {
            'id': 's_method_' + method.carrier_code + '_' + method.method_code,
            'aria-labelledby': 'label_method_' + method.method_code + '_' + method.carrier_code + ' ' + 'label_carrier_' + method.method_code + '_' + method.carrier_code
              },
         click: $parent.selectShippingMethod,
         customBinding: $parent.isSelected"
class="radio"/>

I just created a simple custom binding following the instructions of how to do so from the knockout.js tutorial on custom bindings:

File: MyVendor/MyModule/view/frontend/web/js/customBinding.js

define([
    "jquery",
    "ko",
    "uiComponent"
], function($, ko, Component) {
    "use strict";

    ko.bindingHandlers.customBinding = {
       init: function(element, valueAccessor) {
           console.log("I am a custom binding");
           console.log(element);
           console.log(valueAccessor);
       }
    };

});

I changed the shipping component's js file to point to my shipping.js, which is where the template is specified.

File: MyVendor/MyModule/view/frontend/layout/checkout_index_index.xml

    <referenceBlock name="checkout.root">
        <arguments>
            <argument name="jsLayout" xsi:type="array">
                <item name="components" xsi:type="array">
                    <item name="checkout" xsi:type="array">
                        <item name="children" xsi:type="array">
                            <item name="steps" xsi:type="array">
                                <item name="children" xsi:type="array">
                                    <item name="shipping-step" xsi:type="array">
                                        <item name="children" xsi:type="array">
                                            <item name="shippingAddress" xsi:type="array">
                                                <item name="component" xsi:type="string">MyVendor_MyModule/js/view/shipping</item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </item>
            </argument>
        </arguments>
    </referenceBlock>
</body>

This is the change i made to the shipping.js file so that it picked up my shipping.html template instead of the default.

File: MyVendor/MyModule/view/frontend/web/js/view/shipping.js

...
var popUp = null;
        return Component.extend({
            defaults: {
                template: 'MyVendor_MyModule/shipping'
            },
... 
2

I got your example working using the module outlined below.

The module directory is as follows:

|   registration.php
|   
+---etc
|       module.xml
|       
\---view
    \---frontend
        +---layout
        |       checkout_index_index.xml
        |       
        \---web
            +---js
            |   \---view
            |           shipping.js
            |           
            \---template
                    shipping.html

checkout_index_index.xml :

<?xml version="1.0"?>

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="checkout" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="checkout.root">
            <arguments>
                <argument name="jsLayout" xsi:type="array">
                    <item name="components" xsi:type="array">
                        <item name="checkout" xsi:type="array">
                            <item name="children" xsi:type="array">
                                <item name="steps" xsi:type="array">
                                    <item name="children" xsi:type="array">
                                        <item name="shipping-step" xsi:type="array">
                                            <item name="children" xsi:type="array">
                                                <item name="shippingAddress" xsi:type="array">
                                                    <item name="component" xsi:type="string">Your_Module/js/view/shipping</item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

shipping.js :

define([
    'Magento_Checkout/js/view/shipping',
    'ko'
], function (Shipping, ko) {
    'use strict';

    ko.bindingHandlers.customBinding = {
        init: function (element, valueAccesor) {
            console.log('I am a custom binding.');
            console.log(element);
            console.log(valueAccesor);
        }
    };

    return Shipping.extend({
        defaults: {
            template: 'Your_Module/shipping'
        }
    });
});

shipping.html was copied from Magento_Checkout/view/frontend/web/template/shipping.html and modified in the same way as what you posted.

  • I didn't see the updates you made until after I posted. Looks like all I did different is place the ko.bindHandlers directive inside of the shipping.js file. – Aaron Allen Aug 16 '16 at 1:17
  • Hi Aaron awesome, let me give your solution a whirl. Question, is that the only way we can add custom bindings? – Noemi Quezada Aug 16 '16 at 17:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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