Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout Components - Custom Component Loaders

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/[email protected]/dist/knockout.js:270:48)
    at cloneTemplateIntoElement (http://localhost:8081/lib/bower/[email protected]/dist/knockout.js:3644:41)
    at null.callback (http://localhost:8081/lib/bower/[email protected]/dist/knockout.js:3621:21)
    at Function.ko_subscribable_fn.notifySubscribers (http://localhost:8081/lib/bower/[email protected]/dist/knockout.js:1103:38)
    at http://localhost:8081/lib/bower/[email protected]/dist/knockout.js:3151:54
    at http://localhost:8081/lib/bower/[email protected]/dist/knockout.js:3169:21
    at http://localhost:8081/lib/bower/[email protected]/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)
like image 266
Carlos Mendes Avatar asked Feb 04 '26 15:02

Carlos Mendes


1 Answers

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); } 
    
like image 82
nemesv Avatar answered Feb 09 '26 01:02

nemesv



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!