Question

So referring to this jsfiddle: http://jsfiddle.net/Gaa3G/ I am trying to mix in some javascript functions to manipulate the dynatree with the knockout viewmodel. The code is getting called but nothing is happening (apart from my debug alert is showing up).

View (html):

<script id="itemTmpl" type="text/html">
    <li>
        <span >
            <span data-bind="text: name" />
            <input type="checkbox" data-bind="checked: isManager" />
        </span>
        <ul data-bind="template: { name: 'itemTmpl', foreach: children }"></ul>
    </li>
</script>
<button data-bind="click: addNodes">Add Nodes</button>

Viewmodel: (part of it anyway, the rest can be seen on the jsfiddle)

            self.addNodes = function() {
                alert("I'm adding a node...");
                var rootNode = $("#dynatree").dynatree("getRoot");
                var childNode = rootNode.append({
                    title: "Programatically addded nodes",
                    tooltip: "This folder and all child nodes were added programmatically.",
                    isFolder: true
                });
                childNode.append({
                    title: "Document using a custom icon",
                    icon: "customdoc1.gif"
                });
            };

On my dev computer I see an error with this same code saying "cannot call methods on dynatree prior to initialization; attempted to call method 'getRoot'" but I don't see this error on jsfiddle. This may, or may not, be related!

So am I missing something here? Is this some arcane problem with the specific plugin (dynatree)? (I'd guess not as there are lots of similar error messages appearing on google searches for other jquery-related plugins that seem to be to do with the "setTimeOut" in the knockout custom binding handler. I've no idea why the setTimeout is in there, I just copied it from the original jsfiddle!

Edit 1: So it occurred to me to update the observable array - after all, that's what the tree is bound to!

I added this to my "addNodes" method:

            var bob = new Person({
                id: 3,
                name: 'Bob',
                isManager: true,
                children: []
            });
            self.persons.push(bob);

and lo and behold, "bob" is indeed added to the tree.

Where this could become an issue is in adding something to a specific node as the tree still seems to think it's not initialized when it's bound to a viewmodel and this prevents things like "getRoot" working. Hopefully Martin will turn up at some point and offer an opinion on this!

Was it helpful?

Solution

Basically, you're calling the .dynatree() on the wrong node.

You have data-bind="dynatree:{}" on the inner UL element, not on the #dynatree element. Hence, this UL is the root node.

Update it this way:

             self.addNodes = function() {
                alert("I'm adding a node...");

                // use the correct selector below:
                var rootNode = $("#dynatree > ul").dynatree("getRoot");

                // call the proper method .addChild instead of .append
                var childNode = rootNode.addChild({
                    title: "Programatically addded nodes",
                    tooltip: "This folder and all child nodes were added programmatically.",
                    isFolder: true
                });
                childNode.addChild({
                    title: "Document using a custom icon",
                    icon: "customdoc1.gif"
                });
            };

Updated demo

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top