11 februari 2016

Knockout.js in Magento 2

Magento 2 uses the Knockout.js framework to dynamically build some parts of it's frontend. Knockout.js eases working with dynamic javascript user interfaces by making use of the Model-View-ViewModel (MVVM) pattern.

Features of Knockout.js

  • Observables and dependency tracking
  • Declarative bindings
  • Templating

Observables means that you define data models in javascript that you pick for example via ajax. You than 'connect' these models with elements in a template. Does anything change in your data model than the user interface is updated automatically. This can also work the other way around. With dependency tracking we can setup chains of relationships between model and data, to transform and combine it.

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.

Benefits of using MVVM in javascript

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 templates folder.

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 app/design/frontend/<your-theme-vendor>/<your-theme>/Magento_Checkout/web/template/minicart/content.html

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 foreach binding.

<!-- 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 template binding.

<!-- 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 -->

to:

<!-- 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'.

Summary

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.


Geschreven door:

Quinten Clause

Terug naar blog overzicht