2

I am developing an application that needs to dynamically generate HTML based on certain values. I have the following code where I want the dynamic HTML to go:

<div data-bind="html: extraHTML"></div>

I have an object setup within my javascript file that contains assorted blocks of HTML code that will be chosen once the application has been started. For example one of the object contains the following:

{ type: 'Int', html: '<input style=\'margin: 0\'type=\'number\' min=\'0\' data-bind=\'value: selectedExtra, valueUpdate: \'input\'\' />' }

When I run the application I don't get any errors and the HTML is bound correctly however, when I insert a value into the input field the observable 'selectedExtra' does not update. When I replace the div tag containing the "html" binding with the following:

<input style="margin: 0" type="number" min="0" data-bind="value: selectedExtra, valueUpdate: 'input'">

The observable updates just fine doing this. What I am wondering is if there is anyway to dynamically assign a "value" binding within an "html" binding and have the value actually update. Perhaps there is another solution that I have missed?

Any help would be greatly appreciated, thanks!

Update

I have created a jsfiddle to demonstrate the problem here.

ThreadedLemon
  • 489
  • 1
  • 9
  • 25

1 Answers1

5

when you call applyBindings, ko traverses the dom nodes to "bind" to the elements. Your html is generated, so ko.applyBindings is never called for those elements.

You have 2 options: - Use templates as commented by wayne, (recommended) - If you really want to generate html from an observable and bind the ViewModel, you could use a custom binding. You are actually creating some custom templating system here.

html:

<div data-bind="htmlTemplate:html"></div>

bindinghandler:

ko.bindingHandlers.htmlTemplate = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
       // NOTE: you could return false and ommit the update code, it probably works, but this way you have more control what happens when the html is updated
       return { controlsDescendantBindings:true };
    },
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // remove old bindings
        ko.cleanNode(element);

        // update the inner html, unrwap to support observables and/or normal properties            
        element.innerHTML=ko.unwrap(valueAccessor());

        // apply the view model to the content of the element
        ko.applyBindingsToDescendants(viewModel,element);
    }
};

JSFIDDLE: http://jsfiddle.net/martijn/6b87vw3L/

Martijn
  • 1,440
  • 11
  • 18
  • [`cleanNode` does not remove old bindings](http://stackoverflow.com/questions/15063794/can-cleannode-be-used-to-clean-binding/15069509#15069509) – Roy J Apr 19 '17 at 13:15