Knockout Components - Custom Component Loaders

knockout-components, knockout.js, systemjs

Solution

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); } 

Problem

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) ```

Original source