I'm using Knockout Components and with System.js for module loading.
I have a custom component loader:
var myComponentLoader = {
loadComponent: function(name, componentConfig, callback) {
System.import(componentConfig.myLoader)
.then(function(loadedComponent) {
var result = {
template: ko.utils.parseHtmlFragment(loadedComponent.componentTemplate),
createViewModel: loadedComponent.MyComponentViewModel
}
callback(result);
})
// .catch(function(myError){
// alert(myError);
// callback(null);
// });
}
};
// Register it
ko.components.loaders.unshift(myComponentLoader);
ko.components.register('my-component', { myLoader: './app/components/components' });
But this fails with the following message:
TypeError: undefined is not a function {stack: (...), message: "undefined is not a function"}
This is how my result.template looks like:
<div>This is my component template</div>
<div data-bind="text: myName"></div>
This is how my result.createViewModel looks like:
function MyComponentViewModel(params) {
// Set up properties, etc.
this.myName = ko.observable("Amy Smith");
this.doSomething(params);
this.boundAt = ko.observable(moment().format());
}
Here is the full error:
Potentially unhandled rejection [1] TypeError: undefined is not a function
at Object.ko.utils.cloneNodes (http://localhost:8081/lib/bower/knockout@3.3.0/dist/knockout.js:270:48)
at cloneTemplateIntoElement (http://localhost:8081/lib/bower/knockout@3.3.0/dist/knockout.js:3644:41)
at null.callback (http://localhost:8081/lib/bower/knockout@3.3.0/dist/knockout.js:3621:21)
at Function.ko_subscribable_fn.notifySubscribers (http://localhost:8081/lib/bower/knockout@3.3.0/dist/knockout.js:1103:38)
at http://localhost:8081/lib/bower/knockout@3.3.0/dist/knockout.js:3151:54
at http://localhost:8081/lib/bower/knockout@3.3.0/dist/knockout.js:3169:21
at http://localhost:8081/lib/bower/knockout@3.3.0/dist/knockout.js:3198:29
at eval (http://localhost:8081/app/components/components-bootstrapper.js!eval:32:13)
at O (http://localhost:8081/lib/es6-module-loader.js:7:7439)
at K (http://localhost:8081/lib/es6-module-loader.js:7:7071)
To provide your custom configuration handling logic you need to implement the loadComponent
method as described in the documentation.
However you need to watch out what you return from it, because according to the documentation:
The template
property has to contain an array of DOM nodes: so if your loader loads a string you need to parse it first with:
template: ko.utils.parseHtmlFragment(loadedComponent.componentTemplate)
The createViewModel
has to contain a factory function, so not directly your view model constructor function. So you need to wrap it with
createViewModel: function (params, componentInfo) { return new loadedComponent.viewModel(params, componentInfo); }