0

最初の次元 (テーブルの行) と 2 番目の次元 (行のセル) を持つ 2 次元の並べ替え可能なコンテナーを作成しています。

セルは、行内、既存の行、動的に作成された新しい行にドラッグできる必要があります。空の行は動的に削除する必要があります。セルは、行内のすべてのスペースを占めるように構成されています。

カスタム Knockout ソート可能バインディング (updateイベントなど) を編集するには?

前:

前

後:

後

更新の問題:

  • セル ( .sortable-cell) を新しい行 ( .sortable-table/ .sortable-row) にドラッグすると、viewModel は更新されますが、UI は更新されません
  • セル ( ) を新しい行 ( / ).highlight-horizontalにドラッグすると、プレースホルダー ( ) が表示されない.sortable-cell.sortable-table.sortable-row

//connect items with observableArrays
ko.bindingHandlers.sortableList = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    $(element).data("sortList", valueAccessor().data); //attach meta-data
    $(element).sortable({
      placeholder: valueAccessor().placeholder,
      start: function(event, ui) {},
      change: function(event, ui) {},
      update: function(event, ui) {
        var item = ui.item.data("sortItem");
        if (item) {
          //identify parents
          var originalParent = ui.item.data("parentList");
          var newParent = ui.item.parent().data("sortList");
          //identify viewModel
          var viewModel = bindingContext.$root;
          //figure out its new position
          var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]);

          if (ui.item.parent()[0].classList.contains("sortable-row")) {
            //Row already exists
            console.log("true");
          } else {
            //Row doesn't exist, create new row (PROBLEM WITH UPDATE HERE)
            newParent().splice(position, 0, {
              "children": ko.observableArray([])
            });
            newParent = newParent()[position].children;
          }

          //Update item position
          originalParent.remove(item);
          newParent.splice(position, 0, item);
          
          //Remove empty lists
          var children = viewModel.children();
          for (var i = 0; i < children.length; i++) {
            if (children[i].children().length == 0) {
              viewModel.children.remove(children[i]);
              console.log(children);
            }
          }

          //Update UI
          ui.item.remove();

          //Debug data model
          console.log("final viewModel");
          var children = viewModel.children();
          for (var i = 0; i < children.length; i++) {
            console.log(children[i].children());
            for (var j = 0; j < children[i].children().length; j++) { 
            	console.log(children[i].children()[j].children(),children[i].children()[j].content());
            }
          }
        }

      },
      connectWith: '.sortable-container'
    });
  }
};
//attach meta-data
ko.bindingHandlers.sortableItem = {
  init: function(element, valueAccessor) {
    var options = valueAccessor();
    $(element).data("sortItem", options.item);
    $(element).data("parentList", options.parentList);
  }
};
var self = this;
var viewModel = function() {
  var self = this;
  self.children = ko.observableArray(
    [{
      "children": ko.observableArray([{
        "content": ko.observable("Item 1"),
        "children": ko.observableArray([])
      }, {
        "content": ko.observable("Item 2"),
        "children": ko.observableArray([])
      }, {
        "content": ko.observable("Item 3"),
        "children": ko.observableArray([])
      }])
    }, {
      "children": ko.observableArray([{
        "content": ko.observable("Item 4"),
        "children": ko.observableArray([])
      }])
    }, {
      "children": ko.observableArray([{
        "content": ko.observable("Item 5"),
        "children": ko.observableArray([])
      }, {
        "content": ko.observable("Item 6"),
        "children": ko.observableArray([])
      }])
    }]
  );
};
ko.applyBindings(new viewModel());
.sortable-table {
  border: 1px red solid;
  padding: 10px 0px;
  list-style-type: none;
  width: 100% !important;
  display: table !important;
}
.sortable-table .sortable-row {
  height: 100% !important;
  display: table-row !important;
  padding: 5px 0px;
}
.sortable-table .sortable-cell {
  border: 1px solid green;
  display: table-cell !important;
  cursor: move;
}
.sortable-table .sortable-cell p {
  display: inline;
  margin: 0 !important;
}
.sortable-table .highlight-vertical {
  width: 5px !important;
  display: table-cell !important;
  background-color: blue !important;
}
.sortable-table .highlight-horizontal {
  height: 5px !important;
  width: 100% !important;
  display: block !important;
  background-color: blue !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rniemeyer.github.com/KnockMeOut/Scripts/jquery.tmpl.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>

<div class="sortable-container" data-bind="template: { name: 'rowTmpl', foreach: $data.children, templateOptions: { parentList: $data.children } }, sortableList: { data: $data.children, placeholder: 'highlight-horizontal' }">
</div>

<script id="rowTmpl" type="text/html">
  <div class="sortable-table">
    <div class="sortable-row sortable-container" data-bind="template: { name: 'cellTmpl', foreach: $data.children, templateOptions: { parentList: $data.children } }, sortableList: { data: $data.children, placeholder: 'highlight-vertical' }">
    </div>
  </div>
</script>

<script id="cellTmpl" type="text/html">
  <div class="sortable-cell" data-bind="sortableItem: { item: $data, parentList: $item.parentList }">
    <p data-bind="text: $data.content"></p>
  </div>
</script>

4

1 に答える 1

0

The problem was on line newParent.splice(position, 0, {"children": ko.observableArray([])});. newParent was called as newParent(), which was causing the problem.

//connect items with observableArrays
ko.bindingHandlers.sortableList = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    $(element).data("sortList", valueAccessor().data); //attach meta-data
    $(element).sortable({
      placeholder: valueAccessor().placeholder,
      start: function(event, ui) {},
      change: function(event, ui) {},
      update: function(event, ui) {
        var item = ui.item.data("sortItem");
        if (item) {
          //identify parents
          var originalParent = ui.item.data("parentList");
          var newParent = ui.item.parent().data("sortList");
          //identify viewModel
          var viewModel = bindingContext.$root;
          //figure out its new position
          var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]);

          if (ui.item.parent()[0].classList.contains("sortable-row")) {
            //Row already exists
            console.log("true");
          } else {
            //Row doesn't exist, create new row (PROBLEM WITH UPDATE HERE)
            newParent.splice(position, 0, {
              "children": ko.observableArray([])
            });
            newParent = newParent()[position].children;
          }

          //Update item position
          originalParent.remove(item);
          newParent.splice(position, 0, item);
          
          //Remove empty lists
          var children = viewModel.children();
          for (var i = 0; i < children.length; i++) {
            if (children[i].children().length == 0) {
              viewModel.children.remove(children[i]);
              console.log(children);
            }
          }

          //Update UI
          ui.item.remove();

          //Debug data model
          console.log("final viewModel");
          var children = viewModel.children();
          for (var i = 0; i < children.length; i++) {
            console.log(children[i].children());
            for (var j = 0; j < children[i].children().length; j++) { 
            	console.log(children[i].children()[j].children(),children[i].children()[j].content());
            }
          }
        }

      },
      connectWith: '.sortable-container'
    });
  }
};
//attach meta-data
ko.bindingHandlers.sortableItem = {
  init: function(element, valueAccessor) {
    var options = valueAccessor();
    $(element).data("sortItem", options.item);
    $(element).data("parentList", options.parentList);
  }
};
var self = this;
var viewModel = function() {
  var self = this;
  self.children = ko.observableArray(
    [{
      "children": ko.observableArray([{
        "content": ko.observable("Item 1"),
        "children": ko.observableArray([])
      }, {
        "content": ko.observable("Item 2"),
        "children": ko.observableArray([])
      }, {
        "content": ko.observable("Item 3"),
        "children": ko.observableArray([])
      }])
    }, {
      "children": ko.observableArray([{
        "content": ko.observable("Item 4"),
        "children": ko.observableArray([])
      }])
    }, {
      "children": ko.observableArray([{
        "content": ko.observable("Item 5"),
        "children": ko.observableArray([])
      }, {
        "content": ko.observable("Item 6"),
        "children": ko.observableArray([])
      }])
    }]
  );
};
ko.applyBindings(new viewModel());
.sortable-table {
  border: 1px red solid;
  padding: 10px 0px;
  list-style-type: none;
  width: 100% !important;
  display: table !important;
}
.sortable-table .sortable-row {
  height: 100% !important;
  display: table-row !important;
  padding: 5px 0px;
}
.sortable-table .sortable-cell {
  border: 1px solid green;
  display: table-cell !important;
  cursor: move;
}
.sortable-table .sortable-cell p {
  display: inline;
  margin: 0 !important;
}
.sortable-table .highlight-vertical {
  width: 5px !important;
  display: table-cell !important;
  background-color: blue !important;
}
.sortable-table .highlight-horizontal {
  height: 5px !important;
  width: 100% !important;
  display: block !important;
  background-color: blue !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rniemeyer.github.com/KnockMeOut/Scripts/jquery.tmpl.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>

<div class="sortable-container" data-bind="template: { name: 'rowTmpl', foreach: $data.children, templateOptions: { parentList: $data.children } }, sortableList: { data: $data.children, placeholder: 'highlight-horizontal' }">
</div>

<script id="rowTmpl" type="text/html">
  <div class="sortable-table">
    <div class="sortable-row sortable-container" data-bind="template: { name: 'cellTmpl', foreach: $data.children, templateOptions: { parentList: $data.children } }, sortableList: { data: $data.children, placeholder: 'highlight-vertical' }">
    </div>
  </div>
</script>

<script id="cellTmpl" type="text/html">
  <div class="sortable-cell" data-bind="sortableItem: { item: $data, parentList: $item.parentList }">
    <p data-bind="text: $data.content"></p>
  </div>
</script>

于 2016-01-22T10:24:57.490 に答える