Hey! Do you want to increase the checkout conversion rate in your Magento 2 store? Try the One Step Checkout module. Enable Google Auto Suggest, add delivery date option, customize the design of the checkout page, and boost your sales!
Knockout implements Model-View-View Model (MVVM) design pattern with templates and allows creating dynamic pages, which change with respect to the actions of a user. The introduction of this library brought significant positive changes to Magento 2 development and made it possible to create a much wider range of responsive frontend components, such as date picker, popups, and other custom design elements. Despite the benefits, implementing Magento 2 solutions with Knockout JS and Magento 2 JS translation is quite complicated for many developers.
So, in this tutorial, we look at how JS Knockout works and how to use it in your Magento 2 projects. But KO is only one of the JS libraries that Magento 2 uses. The others are jQuery and Underscore.
- How Knockout JS works in Magento 2
- How Knockout JS works in Magento 2 UI components
- The great thing about Knockout is
- Knockout observables in action
- Knockout for data exchange between UI components
- Knockout and using a UI component in a page layout
- Knockout and server to UI component data transfer
- Bottom line
How Knockout JS works in Magento 2
How Knockout JS works with Magento 2 UI Components
To be more specific, a UI component implements a part of the MVVM design pattern or, in some cases, extends it. A Model here is a piece of Knockout code that contains the data about the component, and the View is a relevant HTML document that describes how the component is rendered.
The frontend js files are conventionally located as follows:
To make it more vivid, consider the checkout component as an example.
First, we access the Model via module-checkout/view/frontend/web/js/view/review/actions/default.js, and see the following code representation:
The path to the component template is shown in the defaults section of the component and takes the form of an object with the key named template. The Model contains information about all the functions that will be used in the View part of the component. Also, the Model is used to declare observable variables.
Second, the View is located in the module-checkout/view/frontend/web/template/review/actions/default.html and looks as below:
The component template contains special Knockout directives used for binding the ViewModel with the template.
For more information about Knockout directives and binding, check the Knockout official documentation.
The great thing about Knockout
While observables are perfect for detecting and responding to changes of one object, working with changes in a collection of things requires an observableArray. The observableArray tracks which objects are in the array, yet not their state. Put simply, the observableArray notifies subscribers when objects are added, removed, filtered, rearranged, etc.
Overall, observables help developers create logic for diverse cases that require an instant reaction to changes of certain objects.
Knockout observables in action
Now, let’s consider an example of using JS knockout observables in Magento 2. We access the Model via the path module-customer/view/frontend/web/js/view/authentication-popup.js and declare the isLoading variable as observable using a relevant keyword – observable.
Now, let’s move on to the View part which also contains the isLoading variable. The path is: module-customer/view/frontend/web/template/authentication-popup.html.
Finally, take a look at an example of an event subscription:
We access module-checkout/view/frontend/web/js/view/cart/totals.js and see:
In the code, you can see that subscription regards the Totals observable. Now when the Totals changes, a related function will trigger the Resize event.
Knockout for data exchange between UI components
Here’s an example of the model of the Checkout Module that we access via module-checkout/view/frontend/web/js/model/shipping-service.js:
Pay attention to the setShippingRates method that affects an observable variable named shippingRates. This method is used in the following model as well module-checkout/view/frontend/web/js/model/shipping-rate-processor/customer-address.js:
In this model, we apply dependencies to transfer the shippingService model into the customerAddress model and use the method setShippingService of the shippingService model. Also, the observable isLoading variable is updated. This way, we connect the customerAddress model to the shippingService model and enable data exchange between the two.
Knockout and using a UI component in a page layout
Now, let’s look at an example of implementing a UI component in a layout file. After we access the XML file located in Amasty/Extrafee/view/frontend/layout/checkout_cart_index.xml, we get:
In the component section, we set the route to the Model file responsible for the Knockout code of the component. The View template can be specified either in the Knockout code or in the config section of the layout of the page (that is checkout_cart_index in our case).
This is how it looks like in the example above:
Below you can see fragments of the code of the component Block in the Extra Fee Module (Amasty_Extrafee/js/view/checkout/cart/block).
In the Model Amasty/Extrafee/view/frontend/web/js/view/checkout/cart/block.js, we see:
And the View model located in Amasty/Extrafee/view/frontend/web/template/checkout/cart/block.html looks like this:
Knockout and server to UI component data transfer
Some Magento 2 pages include a LayoutProcessor responsible for component generation. To convey dynamic variables to the frontend, you should create the LayoutProcessor class in the Module folder named Block.
The LayoutProcessor class is inherited from Magento/Checkout/Block/Checkout/LayoutProcessorInterface.
Then, in the LayoutProcessor class, we realize the Process method which accepts the input of a jsLayout variable. The jsLayout is rather an array variable than just a variable as it contains information about all components that belong to this page.
Using this array variable, we can refer to our component and change/add any variables that we need to use on the frontend of the component.
Check this example of realizing the Process method in Amasty/Extrafee/Block/Cart/LayoutProcessor.php:
Today, we looked at how Knockout JS works in Magento 2. In particular, we learned to use Knockout observables in UI components, add UI components to a page layout, enable data exchange between UI components, and allow data transfer from a server to the frontend of a component.
Hope this article helped you to understand Knockout better and looking forward to your comments and ideas in the feed below.
P.S. Special thanks to Oleg Ivanov for the help with this post.