[英]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: 更新问题:
.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不会更新 .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.