0

I've been looking at building a draggable, sortable list in javascript using knockout, and I've found several strictly javacript based implementations that can handle the task, but I haven't been able to get any knockout bindings working for them.

I've taken a look at Knockout Sortable, and even this question seemed to address a similar request, but it just doesn't seem to quite handle what I'm after.

I'm looking for something that behaves more similar to this nested sortable plugin that works with knockout.

Essentially my object structure looks similar to the following:

public class MenuItem {
    public int Id { get; set; }
    public string Name { get; set }
    public MenuItem Children { get; set; }
}

Each menu item can contain any number of other menu items as children, and those children can have children, and so on and so forth.

I'm trying to figure out a way to recursively create these lists and to read them back so that I'm able to make something work.

Has anyone tried something similar, or is there already some bindings out there?

Community
  • 1
  • 1
JD Davis
  • 3,517
  • 4
  • 28
  • 61
  • Have you looked at this? http://stackoverflow.com/questions/34424283/knockoutjs-make-nested-sortable-automatically-expand-when-adding-a-child – Roy J Oct 14 '16 at 22:05
  • I ended up stumbling across the following jsfiddle that seems to do what I need: http://jsfiddle.net/rniemeyer/UHcs6/ – JD Davis Oct 17 '16 at 13:07

1 Answers1

0

Using the following jsfiddle, I managed to make a working version using knockout-sortable: http://jsfiddle.net/rniemeyer/UHcs6/.

To accomplish this, I only slightly modified the source. The hardest portion was getting knockout to find everything correctly after it was dynamically loaded from ajax.

To get knockout to bind correctly to a list of items, I used their mapping plugin in conjunction with their fromJS method.

First you have to define the model for the objects.

var menuItem = function (id, name, menuId, pageId, icon, order, description, menuItems) {
    this.id = ko.observable(id || 0);
    this.name = ko.observable(name || "");
    this.menuItems = ko.observableArray(menuItems || []);
};

Next, you have to build out from object from the returned ajax data.

$.ajax({
    type: "GET",
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    url: 'URL',
    success: function (data) {
        this.menuItems(ko.mapping.fromJS(data)());
        this.menuItems.notifySubscribers();
    }.bind(this),
    error: function (returndata) {
        alert("Error:\n" + returndata.responseText);
    }
});

From there, everything should work properly if you've setup your recursive template properly, like so:

<span data-bind="text: name"></span>
<ul data-bind="sortable: { template: 'childTmpl', data: menuItems }"></ul>

<script id="childTmpl" type="text/html">
    <li>
        <span data-bind="text: name"></span>
        <ul data-bind="sortable: { template: 'childTmpl', data: menuItems }"></ul>
    </li>   
</script>
JD Davis
  • 3,517
  • 4
  • 28
  • 61