0
votes

I am looking for a way to implement a simple nested/nestable tree structure in KnockoutJS; and it should only allow two levels.

What I found so far is this (and a range of very similar approaches here on SO): Knockout.js nested sortable bindings

However, in this example - and the others, "Containers" cannot become "Children" and vice versa.

Basically, I am looking for a structure like this: http://jsfiddle.net/uhVAW/2/

I.e. it will ultimately render a list with two levels: parent categories and their children.

My tree-structure in the Knockout ViewModel takes this shape (without all the updating logic):

 var VM = function(cats)
 {
    this.categories = ko.observableArray(cats); // bound to the list
 }

 var Category = function
 {
    this.name = ko.observable();
    this.children = ko.observableArray([]); // if exists (i.e. if the cat is a parent), this is bound to a list within the <li>
 }

So, in essence:

  1. Sorting parent level
  2. Sorting children within parents
  3. Children can become parents & vice versa
  4. Only allowing n-levels of nesting (2 in my case)

Cheers!

1

1 Answers

3
votes

Here is a simple tree view using knockout-sortable with recursive templates: http://jsfiddle.net/rniemeyer/Lqttf/

The view model would just look like:

var TreeItem = function(name, children) {
   this.name = ko.observable(name);
   this.children = children && ko.observableArray(children);
};

ko.applyBindings({
    root: new TreeItem("root", [
       new TreeItem("A", [
          new TreeItem("A1"),
          new TreeItem("A2")
       ]),
       new TreeItem("B", [
          new TreeItem("B1"),
          new TreeItem("B2")
       ])
    ])
});

The view would look like:

<script id="nodeTmpl" type="text/html">
    <li>
        <a href="#" data-bind="text: name"></a>
        <div data-bind="if: children">
           <ul data-bind="sortable: { template: 'nodeTmpl', data: $data.children }"></ul>            
        </div>
    </li>
</script>

<ul data-bind="template: { name: 'nodeTmpl', data: root }"></ul>