Reputation: 166086
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
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
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:
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