0

Здесь я работаю над кодом, который использует сортировку Knockout. Он должен отображать вложенные сортировки 3+ уровней в глубину.Нокаут вложенной сортируемый источникParent.splice не является функцией

Данные передаются шаблону, но некоторые элементы возвращаются в исходное положение после отбрасывания (например, A, элементы B на самом верхнем уровне).

Как настроить вложенную сортировку, чтобы верхний уровень можно было использовать без ошибки?

ОШИБКА:

knockout-sortable.js:244 Uncaught TypeError: sourceParent.splice is not a function

or

knockout-sortable.js:252 Uncaught TypeError: targetParent.splice is not a function

JSFiddle - Similar working example

var viewModel = function() { 
 
    var self = this; 
 
    self.children = ko.observable([{ 
 
    "name": "A", 
 
    "children": [{ 
 
     "name": "A1", 
 
     "children": [{ 
 
     "name": "A11" 
 
     }, { 
 
     "name": "A12" 
 
     }] 
 
    }, { 
 
     "name": "A2" 
 
    }] 
 
    }, { 
 
    "name": "B", 
 
    "children": [{ 
 
     "name": "B1" 
 
    }, { 
 
     "name": "B2" 
 
    }] 
 
    }]); 
 
} 
 
ko.applyBindings(new viewModel());
ul { 
 
    border: solid 1px green; 
 
    list-style-type: none; 
 
    margin:0px; 
 
} 
 
li { 
 
    padding: 10px; 
 
    border: solid 1px blue; 
 
    margin:0px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<script src="https://rawgithub.com/rniemeyer/knockout-sortable/master/build/knockout-sortable.js"></script> 
 

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

 
<ul data-bind="sortable: { template: 'nodeTmpl', data: $root.children }"></ul>

ответ

-1

Задача решается путем внесения изменений в линии <ul data-bind="template: { name: 'nodeTmpl', data: $root }"></ul> и я удалил $data из некоторых ссылок, потому что это было вызывая ROR.

var viewModel = function() { 
 
    var self = this; 
 
    self.children = [{ 
 
    "name": "A", 
 
    "children": [{ 
 
     "name": "A1", 
 
     "children": [{ 
 
     "name": "A11", 
 
     }, { 
 
     "name": "A12", 
 
     }] 
 
    }, { 
 
     "name": "A2", 
 
    }] 
 
    }, { 
 
    "name": "B", 
 
    "children": [{ 
 
     "name": "B1", 
 
    }, { 
 
     "name": "B2", 
 
    }] 
 
    }] 
 
}; 
 
ko.applyBindings(new viewModel()); 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script> 
 
<script src="https://rawgithub.com/rniemeyer/knockout-sortable/master/build/knockout-sortable.js"></script> 
 

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

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

+0

Предоставленный фрагмент кода все еще не работает. В то время как ошибка исчезла, перетаскивание заставляет элементы либо не двигаться, либо полностью исчезать. Я опубликовал ответ, который решает эти проблемы. Кроме того, удаление блоков '$ data' было ненужным. – Stanislas

0

Решение, предлагаемое Peter Gerhat является неправильным. Проблема заключается в том, что использовался массив observable, а не observableArray.

Ошибка указывает, что sourceParent (который представляет собой коллекцию на модели, с которой перемещается элемент), не имеет функции splice. Что правильно, наблюдаемый не имеет функции splice, а array или observableArray. То же самое относится к targetParent (который представляет собой коллекцию на viewmodel, на которую перемещается элемент).

Чтобы сделать начальную работу образца, все, что нужно сделать, это изменить observable на observableArray.

Однако, как вы заметили в исходном примере и решении, предоставленном Peter Gerhat, несмотря на то, что ошибка не была выбрана, она по-прежнему не работает должным образом. Вы заметите, что пока вы перетаскиваете элементы, они вообще не двигаются или исчезают.

Решение состоит в том, чтобы превратить каждый array в observableArray, чтобы они могли быть обновлены sortable -связыванием.

var viewModel = function() { 
 
    var self = this; 
 
    self.children = ko.observableArray([{ 
 
    "name": "A", 
 
    "children": ko.observableArray([{ 
 
     "name": "A1", 
 
     "children": ko.observableArray([{ 
 
     "name": "A11" 
 
     }, { 
 
     "name": "A12" 
 
     }]) 
 
    }, { 
 
     "name": "A2" 
 
    }]) 
 
    }, { 
 
    "name": "B", 
 
    "children": ko.observableArray([{ 
 
     "name": "B1" 
 
    }, { 
 
     "name": "B2" 
 
    }]) 
 
    }]); 
 
} 
 
ko.applyBindings(new viewModel());
ul { 
 
    border: solid 1px green; 
 
    list-style-type: none; 
 
    margin: 0px; 
 
} 
 

 
li { 
 
    padding: 10px; 
 
    border: solid 1px blue; 
 
    margin: 0px; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<script src="https://rawgithub.com/rniemeyer/knockout-sortable/master/build/knockout-sortable.js"></script> 
 

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

 
<ul data-bind="sortable: { template: 'nodeTmpl', data: $root.children }"></ul>