What is KnockoutJS and how is it relevant in Magento 2?

If you have just started to learn Magento or have already been doing for some time, there is a higher chance that you have not given a deeper thought about learning Knockout JS. But, it is vital to understand Knockout JS as its “data-binding” concept has been used pretty well in some crucial elements of Magento such as minicart and checkout.

So in this blog, we will be explaining about Knockout JS, and hopefully, when you reach the end of it, you’ll be making knockout apps in Magento. So sit back, relax, and let the journey begin.

Want to skip the basics and go directly to the main section? Click here

What is Knockout JS?

Knockout JS is a Javascript library which uses the MVVM pattern to bind data to certain DOM elements. Within Magento, we usually define a View-Model (which is a .js file) and a Template (which is a .html file), and the data in the template file is bound to the view-model, meaning whenever the data in the view-model changes, the template file changes too.

 

Why use data-binding?

Some of you might be asking "Well can't we just use some library like jQuery to do the DOM parsing manually?", And the answer is, of course, you can. You don't even need jQuery. You can do all the DOM manipulations with core Javascript as well. But libraries like these are there to help us in writing standardized, maintainable, and beautiful code. Here's a simple example, let's say there's a page where the number of visitors is being displayed on 3 separate sections of the page

<div class="visitors"></div>
<!-- Some other HTML -->
<div class="visitors"></div>
<!-- Some other HTML -->
<div class="visitors"></div>

Now our Javascript would look something like this, which would fetch new visitor data every second

<script type="text/javascript">
    (function ($) {
        var visitors = 0;
        var fetchVisitorUrl = "...";
        var fetchVisitors = function () {
            $.get(fetchVisitorUrl, function (data) {
                visitors = data.visitors;
                $('.visitors').html(visitors);
                setTimeout(fetchVisitors, 1000);
            });
        };
        fetchVisitors();
    })(window.jQuery);
</script>

See the $('.visitors').html(visitors);? That line is responsible for actually making the DOM manipulation. Without that, even when the new visitor data is fetched, it'll not be visible on the page. Now suppose a new developer working on your project decided to implement a better way to fetch visitor data? Using sockets perhaps? Then he/she would also have to write $('.visitors').html(visitors);in his/her code. Hence the code becomes messy and redundant. Using data-binding, we change only the View-Model, and the View changes automatically.

 

Knockout JS and Magento 2

To make a knockout app in Magento 2, first we create a new module. Next in our template file, we write the following

<?php
/* @var Codilar\HelloWorld\Block\Hello $block */
?>
<div data-bind="scope: 'knockout-tutorial'">
    <!-- ko template: getTemplate() --><!-- /ko -->
</div>
<script type="text/x-magento-init">
    {
        "*": {
            "Magento_Ui/js/core/app": {
                "components": {
                    "knockout-tutorial": {
                        "component": "Codilar_HelloWorld/js/viewModel",
                        "template" : "Codilar_HelloWorld/template"
                    }
                }
            }
        }
    }
</script>

This is basically initiating the Magento_Ui/js/core/appwidget with the components passed as options, using the text/x-magento-init tag. The data-bind="scope: 'knockout-tutorial'"says knockout to use the knockout-tutorialcomponent and template inside that DIV.

 

Next, we write our component file

app/code/Codilar/HelloWorld/view/frontend/web/js/viewModel.js

define([
    'uiComponent',
    'ko'
], function(Component, ko) {
    return Component.extend({
        clock: ko.observable(""),
        initialize: function () {
            this._super();
            setInterval(this.reloadTime.bind(this), 1000);
        },
        reloadTime: function () {
            /* Setting new time to our clock variable. DOM manipulation will happen automatically */
            this.clock(Date());
        },
        getClock: function () {
            return this.clock;
        }
    });
});

The View-Models inside of a Magento 2 application, must return a Component.extendfunction call, where the Component is an object of the uiComponent, which were required here. Inside our Component.extend, we pass an object, which must contain an initialize function which will be the "constructor of our class", so to speak.

 

And finally, we create our template file

app/code/Codilar/HelloWorld/view/frontend/web/template/template.html

<!-- My View-Model file is Codilar_HelloWorld/js/viewModel -->
<h1 data-bind="text: getClock()"></h1>

Now if we hit the url http://mywebsite.com/helloworld/ we should see a clock which should change every second, even though we didn't explicitly do any DOM manipulations.

That's all about how Magento 2 uses the knockout JS bindings. Do let us know in the comment section below about what you want my next Magento tutorial blog to be about. Also, don't forget to check our previous tutorials!

Click here to download a zip copy of the above-mentioned project

Watch the video to learn more about KnockoutJS in Magento 2 (Demo).

Previous Tutorials

What are widgets in jQuery & how are they different from regular objects/functions?

How to create a “HELLO WORLD” module in Magento 2?