Reputation: 1054
I have a strange problem with knockout js component loaded by require js. The component is very simple.
define([
'jquery',
'knockout'
], function ($, ko) {
function ViewModel(params) {
var self = this;
this.test = 'test';
}
ViewModel.prototype.fetchData = function() {
var self = this;
console.log(this.test);
};
ViewModel.prototype.init = function() {
console.log(this.test);
this.fetchData();
};
ko.components.register('my-component', {
viewModel: ViewModel,
template: '<span data-bind="template: { afterRender: init }"></span>'
});
});
Now, the template binding is able to call the view models init method, but this method itself can not access the fetchData method, because inside the method this is bound to the Window object instead of the view model.
I prepared a fiddle to show the error case: http://jsfiddle.net/ask4artur/3f6jsa4m/47/
Upvotes: 1
Views: 264
Reputation: 23372
I believe knockout does not call the afterRender
method in the this-context of $data
automatically. You can set $data
as this
by using bind
like so:
data-bind="template: { afterRender: init.bind($data) }
var i = 0;
var ViewModel = function() {
this.nr = "Instance " + i++;
}
ViewModel.prototype.logNr = function() {
console.log(this.nr);
};
ko.components.register('test', {
viewModel: ViewModel,
template: '<div data-bind="template: { name: \'testTemplate\', afterRender: logNr.bind($data) }"></div>'
});
ko.applyBindings();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="component: {name: 'test'}"></div>
<div data-bind="component: {name: 'test'}"></div>
<div data-bind="component: {name: 'test'}"></div>
<div data-bind="component: {name: 'test'}"></div>
<div data-bind="component: {name: 'test'}"></div>
<script type="text/html" id="testTemplate">
<div data-bind="text: nr, click: logNr"></div>
</script>
Upvotes: 3