Magento 2 is heavily using Knockout Js on frontend. You can find Knockout in Magento 2 on almost every page.
For example in : on minicart vendor\magento\module-checkout\view\frontend\templates\cart\minicart.phtml
<div id="minicart-content-wrapper" data-bind="scope: 'minicart_content'"> <!-- ko template: getTemplate() --><!-- /ko --> </div>
To understand how it works, I created a simple module Magento 2 Knockout Js Simple Module to explain it.
You can download it and check te result of this tutorial on github. :
Magento2-Knockout-JS-Simple-Module
This module allows us to add/remove seat reservation and calculate total charge dynamically using Knockout JS.
You can follow my instruction on github Readme file for installing this module.
Access it via http://your_locahost/knockout/index/view
1/ Introduce Knockout Js.
Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model. It implements Model-View-View Model (MVVM) design pattern.
If you’re not familiar with Knockout Js. You can look at : Knockout site .
So, in quick conclusion, KO provides a client side JS abstraction that enhances your stock JavaScript library in the following ways:
1. Greatly simplifies synchronization between the client UI and server.
2. Leverages MVVM design pattern to increase modularity and provide for a clean separation of concerns and cohesive implementations.
3. Keeps UI model state management on the client (where it belongs).
4. Decreases (potentially) the size of server responses and client/server traffic in general (thereby speeding up our apps).
2/ How Knockout Js simple module works:
2.1/ My simple module create a new route : knockout/index/view to load a custom template Grid.phtml:
(app\code\Thienphucvx\Knockout\view\frontend\templates\grid.phtml)
In file : app\code\Thienphucvx\Knockout\view\frontend\layout\knockout_index_view.xml
<block class="Thienphucvx\Knockout\Block\ViewAbstract" before="-" cacheable="false" template="Thienphucvx_Knockout::grid.phtml">
Here is the content of Grid.phtml:
<div id="block-sample-grid" data-bind="scope:'sample-grid'" class="block"> <!-- ko template: getTemplate() --><!-- /ko --> <script type="text/x-magento-init"> { "#block-sample-grid": { "Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?> } } </script> </div>
2.2/ In grid.phtml, it will load js\view\grid.js file based on knockout_index_view.xml and get right template based on grid.js configuration.
As you can see we set “data-bind=”scope:’sample-grid’“. The row “$block->getJsLayout()” => will read configuration from knockout_index_view.xml
Based on this configuration “<item name=”component” xsi:type=”string”>Thienphucvx_Knockout/js/view/grid</item>“, it will render like this :
“Magento_Ui/js/core/app”: {“components”:{“sample-grid”:{“component”:”Thienphucvx_Knockout\/js\/view\/grid”}}}
=>
It will load “app\code\Thienphucvx\Knockout\view\frontend\web\js\view\grid.js” for component : “sample-grid“.
In “view\frontend\web\js\view\grid.js”: We set default template via this line code
“defaults: {
template: ‘Thienphucvx_Knockout/grid’},”
It means we tell magento 2 that virtual element “<!– ko template: getTemplate() –><!– /ko –>” to load “view\frontend\web\template\grid.html” for displaying content of scope component “sample-grid“.
Summary explain how Knockout Js Module Works
Finally grid.html will be loaded :
<h2>Your seat reservations (<span data-bind="text: seats().length"></span>)</h2> <table> <thead><tr> <th>Passenger name</th><th>Meal</th><th>Surcharge</th><th></th> </tr></thead> <tbody data-bind="foreach: seats"> <tr> <td><input data-bind="value: name" /></td> <td><select data-bind="options: $parent.availableMeals, value: meal, optionsText: 'mealName'"></select></td> <td data-bind="text: formattedPrice"></td> <td><a href="#" data-bind="click: function(data,event){$parent.removeSeat($parent,data);}">Remove</a></td> </tr> </tbody> </table> <button data-bind="click:addSeat, enable: seats().length < 5">Reserve another seat</button> <h3 data-bind="visible: totalSurcharge() > 0"> Total surcharge: $<span data-bind="text: totalSurcharge().toFixed(2)"></span> </h3>
I believe from that point, you can dig into grid.html to understand how my module works. If you have trouble on understand what is “$parent”, you can read it at here : http://knockoutjs.com/documentation/binding-context.html
Magento 2 use “scope” to binding View-model instead of applying via “ko.applyBindings(new AppViewModel())” as normal Knockout. You can read Alan article to know more about it http://alanstorm.com/magento_2_knockoutjs_integration
Some more resources about Knockout JS on Magento2:
http://www.ibnab.com/en/blog/magento-2/magento-2-ui-knockoutjs-using-container-less-ko-template-gettemplate
http://learn.knockoutjs.com/
http://alanstorm.com/knockoutjs_primer_for_magento_developers
http://magento.stackexchange.com/questions/89492/magento2-knockoutjs-custom-template-binding
COMMENTS