Skip to content Skip to sidebar Skip to footer

Knockout Nested Sortable Lists

I need to build a web page that has two lists that can be swapped around. The lists have items that can also be swapped or moved from one list to the other. I used knockoutjs and k

Solution 1:

I found the problem after a good night sleep. There was several pitfalls in my design above:

  • The nested lists did not have a connectClass that will help knockout-sortable find out where the element can be dragged. Leaving this unspecified makes one of the lists accept either an item or a complete list to be dragged into it.
  • The draggable place holder has a different styling that the lists themselves. This is why the draggable placeholder was not correctly rendered (ref. the resulted screenshot in my question above)
  • There was only one place holder defined, that applied to both a dragged item and a dragged list which is not good.

Here is a fiddle showing the full working solution.

HTML

<divclass="frame"><ulclass="Tasks"data-bind="sortable: {data: TaskLists, connectClass: 'columns', options: { placeholder: 'list-highlight'}}"><liclass="taskList"><spandata-bind="text: Title"style='background: lightgray;'></span><uldata-bind="sortable: {data: Tasks, connectClass: 'columnItems', options : { placeholder: 'ui-state-highlight'}}"><liclass="item"><spanclass="taskName"href="#"data-bind="text: name"></span></li></ul></li></ul></div>

JS

var Task = function(name) {
    this.name = ko.observable(name);
}

var ViewModel = function() {
    varself = this;
    self.tasks1 = ko.observableArray([]);
    self.tasks2 = ko.observableArray([]);
    for (var i=0;i<5;i++){ 
        self.tasks1.push(new Task("This task belongs to list one"));
        self.tasks2.push(new Task("This task belongs to list two"));
    }
    self.TaskList1 = {Tasks: self.tasks1, Title:'List One'};
    self.TaskList2 = {Tasks: self.tasks2, Title:'List Two'};
    self.TaskLists = ko.observableArray([]);
    self.TaskLists.push(self.TaskList1);
    self.TaskLists.push(self.TaskList2);
};

ko.bindingHandlers.sortable.options = {
        //placeholder: 'ui-state-highlight',
        start: function (e, ui) {
            var dragItems = $('.ui-state-highlight');
            var dragLists = $('.list-highlight');
            var elementClass = ui.helper[0].className;
            if(elementClass === "item")
                  dragItems.css("height",ui.helper.outerHeight());
            if(elementClass === "taskList")
                  dragLists.css("height",ui.helper.outerHeight());
        }
    };
ko.applyBindings(new ViewModel());

CSS

.frame{
        padding: 10px;
        overflow:auto;
    }

    .item {
       border: black 1px solid;
       width: 100px;
       background-color: #DDD;
       cursor: move;
       text-align: center;
       margin-top: 2px;
       margin-bottom: 2px;
    }

    .list-highlight{
        width: 100px;
        float:left;
        background: gray;
    }

    .taskList{
        width: 110px;
        float:left;
        background: lightgreen;
    }

    .Tasks{
        width:400px;
        border: 1px#eee solid;
        height: 100%;
    }

    .taskName{
        word-wrap: break-word;
    }

    .ui-state-highlight{
        background: grey;
        border:1px dashed grey;
}

Post a Comment for "Knockout Nested Sortable Lists"