Search code examples
javascriptknockout.jsknockout-components

Knockout Components - Cannot apply bindings more than once


I'm trying to create a page using knockout components, and I'm having some trouble trying to bind multiple components in a page if they aren't added at the same time. As far as I can see I have no way to directly access the viewmodel of the component, to bind it to the specific element.

ko.applyBindings(viewModel, document.getElementById("component1"));

My problem is that, since I thus have to use the more general

ko.applyBindings()

if I add another component to the page at a later time, and want to bind it, I receive the "You cannot apply bindings multiple times to the same element." error.

Is there any way for me to access a components view model and apply it directly?

$('body').append('<div id="compoent1" data-bind=\'component: { name:"someComponent"\}'></div>')
ko.applyBindings(viewModel/*How do I get this?*/, document.getElementById("component1"));

I've tried just using

ko.applyBindings(document.getElementById("component1"));

My explanations is perhaps somewhat hard to understand, here is pseudo code of what I am trying to do:

Add a knockout component
Apply bindings for the knockout component
.... some time later in my single page application
Add another knockout component
Apply bindings for the new knockout component

Solution

  • It seems to me that you're probably trying to add a component using non-knockout methods.

    Once you go knockout, it's better to keep everything in the knockout fold and to resist the temptation of falling back onto jQuery or straight DOM manipulation for the "quick win". It always bites you later... so:

     <foocomponent params="woo:'fwoo'"></foocomponent >
     <!-- ko if:someBooleanObservableThatChangesLater -->
         <myawesomecomponent params="choo:'boo'"></myawesomecomponent >
     <!-- /ko -->
    

    Now we've "added" a second component by changing an observable in our root model (someBooleanObservableThatChangesLater). No re-binding required.

    Your circumstances may be somewhat different to my rather simple example above, but hopefully the intent is clear. You can get similar behaviour by pushing items into an observableArray and using the foreach binding on it so that content gets added to/removed from the DOM whenever you change the observableArray. Once again, no second call to applyBindings is required.