1

In Knockout we make the variable to be observable like var a=ko.observable(); but in Magento 2 without mentioning ko.observable() the variable acts as an observable variable.

  1. This is customer.js file and its path is

vendor/magento/module-customer/view/frontend/web/js/view/customer.js

define([
    'uiComponent',
    'Magento_Customer/js/customer-data'
], function (Component, customerData) {
    'use strict';

    return Component.extend({
        /** @inheritdoc */
        initialize: function () {
            this._super();
            this.customer = customerData.get('customer');
        }
    });
});
  1. This is header.phtml file and it's path is

vendor/magento/module-theme/view/frontend/templates/html/header.phtml

<li class="greet welcome" data-bind="scope: 'customer'">
        <!-- ko if: customer().fullname  -->
        <span class="logged-in"
              data-bind="text: new String('<?= $block->escapeHtml(__('Welcome, %1!', '%1')) ?>').replace('%1', customer().fullname)">
        </span>
        <!-- /ko -->
        <!-- ko ifnot: customer().fullname  -->
        <span class="not-logged-in"
              data-bind='html:"<?= $block->escapeHtml($welcomeMessage) ?>"'></span>
        <?= $block->getBlockHtml('header.additional') ?>
        <!-- /ko -->
    </li>
    <script type="text/x-magento-init">
    {
        "*": {
            "Magento_Ui/js/core/app": {
                "components": {
                    "customer": {
                        "component": "Magento_Customer/js/view/customer"
                    }
                }
            }
        }
    }
    </script>

Question : How this.customer variable from js file becomes ko.observable and acts in phtml file as customer() in <!--ko-->?

3

Notice the line this.customer = customerData.get('customer').

customerData.get() returns a ko.observable({...}).
If you want to dig deeper, you can look at the get function from Magento_Customer/js/customer-data.
This one returns buffer.get(sectionName) (buffer is a variable defined in the same file).
and buffer.get looks like this:

get: function (sectionName) {
    if (!this.data[sectionName]) {
        this.bind(sectionName);
    }
    return this.data[sectionName];
}

So when you request a section from the buffer, if that section already exists it is returned, if not, then it is initialized via the bind function which looks like this:

bind: function (sectionName) {
    this.data[sectionName] = ko.observable({});
}

To conclude... when requesting a section from the customerData object....

  • the first time you request it, it is initialized with ko.observable({}) and returned
  • from the second time forward, it is just returned.

That's why you get an instance of ko.observable even if you didn't declare it yourself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.