Search code examples
knockout.jsbidirectional

Does Knockout support bi-directional binding to styles?


For example, I want to bind a property in the viewmodel to an height of an element so if its height get changed it updates the property. I read this example but it shows only one direction binding: http://knockoutjs.com/documentation/style-binding.html , meaning updating the property will update the style but not otherwise.

What I am thinking of doing is something like that:

<div class="panel-body" data-bind="style: {height: chatParentHeight}">
   <div data-bind="style: { height: chatHeight}">
   </div>
</div>

In view model: self.chatParentHeight = ko.observable(); self.chatHeight = self.chatParentHeight();

So the parent height is monitored for changes and if a change happens it also changes the child element height because it's bound to it. But the viewmodel is not updated when the height style is updated. I tried also with backgroundColor to simplify it , but it doesn't work as well.


Solution

  • The question from your title can be answered using the Knockout source: it's open, and actually pretty easy to go through. To quote the relevant file:

    ko.bindingHandlers['style'] = {
        'update': function (element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor() || {});
            ko.utils.objectForEach(value, function(styleName, styleValue) {
                styleValue = ko.utils.unwrapObservable(styleValue);
    
                if (styleValue === null || styleValue === undefined || styleValue === false) {
                    // Empty string removes the value, whereas null/undefined have no effect
                    styleValue = "";
                }
    
                element.style[styleName] = styleValue;
            });
        }
    };
    

    So the answer is "no": the style binding is not two-way, but then again it's also "yes" as you can write a custom binding handler to do this yourself.

    If your question is actually different, more about how to have two heights related, then check out the other answer.