Alana Storm
Alana Storm

Reputation: 166086

KnockoutJS: What Does Calling applyBindings Without Arguments do?

I'm working through some -- interesting -- code that I didn't write, and came across a RequireJS module that seems to initialize a KnockoutJS instance for the application.

define([
    'ko',
    './template/engine',
    'knockoutjs/knockout-repeat',
    'knockoutjs/knockout-fast-foreach',
    'knockoutjs/knockout-es5',
    './bind/scope',
    './bind/staticChecked',
    './bind/datepicker',
    './bind/outer_click',
    './bind/keyboard',
    './bind/optgroup',
    './bind/fadeVisible',
    './bind/mage-init',
    './bind/after-render',
    './bind/i18n',
    './bind/collapsible',
    './bind/autoselect',
    './extender/observable_array',
    './extender/bound-nodes'
], function (ko, templateEngine) {
    'use strict';

    ko.setTemplateEngine(templateEngine);
    ko.applyBindings();
});

This code calls ko.applyBindings() without a view model. I'm very new to knockout, but all the tutorials I've seen indicate you need to pass applyBindings a viewModel object.

What does calling applyBindings without parameters do, exactly?

My end goal here is to figure out how this application (Magento 2, if anyone's curious) is using Knockout to render things, so I'm looking for reasons a Knockout developer might do something like this.

Upvotes: 1

Views: 1230

Answers (2)

Alana Storm
Alana Storm

Reputation: 166086

Via some comments here and additional research, I was able to come up with the answer I was looking for.

My mistake was thinking ko.applyBindings() main job was to associate a view model (javascript object) with the view (HTML page). While that's one of applyBindings' jobs, applyBindings also starts rendering the view (HTML page). In Knockout's world, rendering the view means (at least?) scanning the HTML page for data-bind attributes, and processing those attributes.

By itself, processing the data-bind attributes with no data would be pretty useful. However, if the application you're using has created custom bindings (as seen in this tutorial), there's no limit to calling what applyBindings can do. In my specific case, Magento 2 has a custom binding named scope that (via some other mechanisms) will bind data for a specific node context.

Upvotes: 1

user3297291
user3297291

Reputation: 23382

Most of knockout's functionality won't make sense without a viewmodel, but that doesn't make it required. You can see in the source that nothing breaks when you don't pass a viewmodel parameter: it just sets the binding context as undefined:

function getBindingContext(viewModelOrBindingContext) {
    return viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext)
        ? viewModelOrBindingContext
        : new ko.bindingContext(viewModelOrBindingContext);
}

A few examples I can think of why one would applyBindings without a viewmodel:

  • Injecting static templates
  • Attaching event listener methods that are in the global context

I must admit though that these feel a bit contrived... I actually don't know why the code you've shown does it...

window.logClick = function(data, event) {
  console.log("Click");
};

ko.applyBindings();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div>
  <div data-bind="template: 'header-template'"></div>

  <button data-bind="click: logClick">click listener in window</button>
</div>



<script id="header-template" type="text/html">

  <h1>A header inserted by template</h2>
  
</script>

Upvotes: 1

Related Questions