Search code examples
htmlknockout.jsknockout-3.0

How to validate knockout data-bind nestings?


Recently ran into a problem where knockout binding to html comments were not well formed because of a nesting problem. I used where an html comment to house a ko if: and then used ko foreach which was bound to an html <div>, but managed to get the nesting wrong. Below is an example of the issue:

<!-- ko if: isGuestCheckout() -->
     <div data-bind="foreach: formSection()">
<!-- /ko>
Simple malformed knockout</div>

In this simple example it is easy to see what the issue is, but in a much larger html block it is much harder to spot the error. I eventually resorted to have html comments for the end of each knockout binding for example <!-- end isGuestCheckout() --> which seems inefficient.

Is anyone aware of a way of validating that knockout data-binds are nested correctly?


Solution

  • I've run into similar issues and what I've done to troubleshoot in those cases is add a "whoami" observable for each nested KO-observable object and drop a simple span in the various nested levels to give me some insight as to what is being bound and where.

    For example, if I have a view model like this...

    var myViewModel = function() {
        var self = this;
        self.whoami = ko.observable("I am the root view model");
        self.items = ko.observableArray(); //This holds an array of myItem
    };
    
    var myItem = function() {
        var self = this;
        self.whoami = ko.observable("I am an item");
    }
    

    Then my HTML looks something like this...

    <div>
        <!-- At this level I expect to see the whoami from the root VM -->
        <span data-bind="text: whoami"/>
    
        <div data-bind="foreach: listOfItems">
            <!-- At this level I expect to see the whoami from the item -->
            <span data-bind="text: whoami"/>
        </div>
    </div>
    

    Doing this has helped me quickly discover Knockout nesting issues. Once I find it then I just pull out the whoami span tags, but I usually end up keeping the whoami observable in the JS in case I need it again.

    I hope this helps! :-)