Knockout嵌套可排序的sourceParent.splice不是一个函数

时间:2016-01-20 15:43:10

标签: knockout.js knockout-2.0 knockout-3.0 knockout-sortable knockout-templating

这里我正在研究使用Knockout sortable的代码。它应该显示深度为3级以上的嵌套排序。

数据传递给模板,但是一些元素在被删除后返回到原始位置(例如 A,B元素位于最高级别)。

我应该如何配置嵌套排序,以便在没有错误的情况下也可以使用最高级别?

错误:

  

knockout-sortable.js:244 Uncaught TypeError:sourceParent.splice不是函数

     

     

knockout-sortable.js:252 Uncaught TypeError:targetParent.splice不是函数

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>

2 个答案:

答案 0 :(得分:1)

Peter Gerhat提供的解决方案不正确。 问题在于使用了observable数组,而不是observableArray

错误表明sourceParent(从中拖动元素的viewmodel上的集合)没有splice函数。哪个是正确的,一个observable没有splice函数,而arrayobservableArray就是targetParent函数。这同样适用于observable(这是拖动元素的viewmodel上的集合)。

要使初始样本有效,所有需要做的就是将observableArray更改为array

但是,正如您将在原始示例和Peter Gerhat提供的解决方案中注意到的那样,即使没有抛出任何错误,它仍然无法正常工作。您会注意到,当您拖动元素时,要么根本不移动,要么消失。

此处的解决方案是将每个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()); - 绑定更新它们。

&#13;
&#13;
ul {
  border: solid 1px green;
  list-style-type: none;
  margin: 0px;
}

li {
  padding: 10px;
  border: solid 1px blue;
  margin: 0px;
}
&#13;
<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>
&#13;
this.http
    .get(url)
    .map((res: Response) => {
        return res.json().map((obj: Type) => {
            return Object.assign(new Type(), obj);
        });
    })
    // And so on  
&#13;
&#13;
&#13;

答案 1 :(得分:-1)

通过对行<ul data-bind="template: { name: 'nodeTmpl', data: $root }"></ul>进行更改并从某些引用中删除$data来解决问题,因为它导致了错误。

&#13;
&#13;
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());     
&#13;
<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>
&#13;
&#13;
&#13;