drdwilcox
drdwilcox

Reputation: 3951

Dynamic binding to dynamic elements in knockout.js

I am trying to build a binding that will allow me to change the type of an input element based on a property in my viewmodel, and bind the value of that input element to another property of my viewmodel.

I have the following fiddle showing what I am trying to accomplish: fiddle

<div data-bind="dynamic: theType, value: 'theValue'"></div>

ko.bindingHandlers.dynamic = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        var vm = valueAccessor();
        var $element = $(element);

        var choice = ko.unwrap(vm) || 'shortText';
        var bindTo = allBindings.get('value');

        if (choice === 'longText') {
            $element.html("<textarea rows='4' data-bind='value: " + bindTo + "' valueUpdate: 'afterkeydown' />");
        } else {
            $element.html("<input type='text' data-bind='value: " + bindTo + "' valueUpdate: 'afterkeydown' />");
        } // if

        ko.applyBindings(viewModel, $element.find(':input')[0]);
    }
};

var vm = {
    theValue: ko.observable(''),
    theType: ko.observable(''),
};
ko.applyBindings(vm);

Unfortunately, everything I have tried results in either the linkage between the element and the viewmodel being lost, or knockout complaining that I cannot apply bindings multiple times to the same element. I know I can do this with templates, but I am wondering why my approach doesn't work.

Does anyone have any suggestions?

Thank you,

Don

Upvotes: 0

Views: 1404

Answers (1)

drdwilcox
drdwilcox

Reputation: 3951

OK. It turned out that all I needed to do was to add:

return { controlsDescendantBindings: true };

from my init method, and knockout and I can get along just fine. See the updated fiddle here: http://jsfiddle.net/X4xXL/2/

Upvotes: 1

Related Questions