简体   繁体   English

二维敲除可排序不更新UI

[英]Two-dimensional knockout sortable not updating UI

I'm creating a two-dimensional sortable container with first dimension (rows in table) and second dimension (cells in a row). 我正在创建一个具有第一维(表中的行)和第二维(行中的单元格)的二维可排序容器。

The cells should be draggable within a row, to existing rows, to new rows created dynamically. 单元格应可在一行中拖动到现有行,也可以拖动到动态创建的新行。 Empty rows should be dynamically deleted. 空行应动态删除。 The cells are configured to occupy all space in a row. 单元被配置为连续占据所有空间。

How to edit the custom Knockout sortable binding (eg update event)? 如何编辑自定义的Knockout可排序绑定(例如, update事件)?

Before: 之前:

之前

After: 后:

后

Update problems: 更新问题:

  • When dragging a cell ( .sortable-cell ) to a new row ( .sortable-table / .sortable-row ) the viewModel gets updated, but not the UI 将单元格( .sortable-cell )拖到新行( .sortable-table / .sortable-row )时,viewModel会更新,但UI不会更新
  • The placeholder ( .highlight-horizontal ) is not displayed, when dragging cell ( .sortable-cell ) to a new row ( .sortable-table / .sortable-row ) 将单元格( .sortable-cell )拖到新行( .sortable-table / .sortable-row )时,不显示占位符( .highlight-horizontal

 //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> 

The problem was on line newParent.splice(position, 0, {"children": ko.observableArray([])}); 问题是在newParent.splice(position, 0, {"children": ko.observableArray([])}); . newParent was called as newParent() , which was causing the problem. newParent被称为newParent() ,这导致了问题。

 //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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM