Features of Knockout.js
- Observables and dependency tracking
- Declarative bindings
With declarative binding we can manipulate more properties of the UI instead of just showing values. Depending on our data model we can change visibility, text, html, css, styles, attributes, ...
Over at learn.knockoutjs.com they have a real nice web app set up that takes you through the basics of using Knockout.js in a 'hands-on' style. It's really fun to work through.
Knockout.js is very similar to Angularjs. But Angularjs is a very complete and large framework with dependency injection, ajax, routing, cookies and much more ... Probably Magento 2 was just looking only for a way to do data-binding. Find out more about the differences between Knockout.js and Angularjs in this comparison article.
Knockout.js makes it easy to separate user tailored dynamic content from the initial generic page source. So the page source can be cached independently from which user requests the page. Dramatically reducing the number of pages that need to be cached.
Take the minicart in the header for example: Each customer will have other items in his or her cart, but yet the minicart is displayed on almost every page. Which means if we would render the minicart in php, we would have to cache each page separately for each user.
And as an extra the user does not have to leave the page when he or she adds new items to his or her cart.
An example of customising the minicart
If you want to write html template structures in Magento that work witk Knockout.js you have to deal with regular
.html files in addition to the traditional
.phtml files. These templates are loaded via ajax. You can usually find these files in
app/code/<vendor>/<module>/view/frontend/web/template/ or in
app/design/frontend/<theme-vendor>/<theme>/<module-vendor>_<module>/web/template/. So they are inside the
template folder inside the
web folder and not in the regular
To modify the minicart we must copy the file
app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html to our theme folder. So we copy the file to
Inside this template file we can use al sorts of code structures like an 'if' structure for example. Say we want to hide elements when the cart is empty, we can add the following around a code block.
<!-- ko if: cart().summary_count == 0 --> <div>some code</div> <!-- /ko -->
Using the syntax with comments like this is called 'containerless control flow syntax'. We could also bind this to the container itself of course. Like so:
<div data-bind="if: cart().summary_count == 0">some code</div>
Similar to the
if binding there is also the
<!-- ko foreach: someArray --><!-- /ko -->
We can also add text that can be translated.
<span class="notice"><!-- ko i18n: 'All prices are tax included.' --><!-- /ko --></span>
Calling another template can be done with the
<!-- ko template: 'path/to/template' --><!-- /ko -->
The part that initially loads the content form the minicart in the header comes from a regular
.phtml file, that can be found
app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml. Here we also see some knockout.js bindings.
For instance we can change the code that shows the counter next to the cart icon from:
<!-- ko if: cart().summary_count --> <!-- ko text: cart().summary_count --><!-- /ko --> <!-- ko i18n: 'items' --><!-- /ko --> <!-- /ko -->
<!-- ko if: cart().summary_count == 1 --> <!-- ko i18n: 'item' --><!-- /ko --> <!-- /ko --> <!-- ko if: cart().summary_count != 1 --> <!-- ko i18n: 'items' --><!-- /ko --> <!-- /ko -->
Now the counter also shows up when there are actually zero items in the cart. And it shows '0 items'.
As you can see: knowing how to work with Knockout.js is an essential tool for frontend developers that have to change Magento 2 layouts and html structures. This is just the tip of the iceberg. If you have the time it can certainly be useful to checkout the official tutorials and documentation for Knockout.js.
Terug naar blog overzicht