Knockout вложенный сортируемый sourceParent.splice не является функцией

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

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

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

ОШИБКА:

knockout-sortable.js: 244 Uncaught TypeError: sourceParent.splice не является функцией

or

knockout-sortable.js: 252 Uncaught TypeError: targetParent.splice не является функцией

JSFiddle - аналогичный рабочий пример

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>


person Peter G.    schedule 20.01.2016    source источник


Ответы (2)


Решение, предложенное Питером Герхатом, неверно. Проблема заключается в том, что использовалось наблюдаемое массива, а не observableArray.

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

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

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

Решение здесь состоит в том, чтобы превратить каждый 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>

person Stanislas    schedule 10.03.2018

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

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>

person Peter G.    schedule 20.01.2016
comment
Предоставленный фрагмент по-прежнему не работает. Пока ошибка исчезла, при перетаскивании элементы либо не перемещаются, либо исчезают полностью. Я опубликовал ответ, который решает эти проблемы. Кроме того, в удалении блоков $data не было необходимости. - person Stanislas; 10.03.2018