我有一个使用冻结/锁定列并具有拖放功能的网格。问题是我只能在解锁列的一侧拖放一行,这不是我想要的。我希望能够从锁定的一侧抓取一行并拖放。IE,如果我从 ID 列中抓取一行,我应该能够拖放它。我希望这是有道理的
$(document).ready(() => {
$.when(LoadGrid()).then(EnableDragAndDropForGrid());
});
let ds = [{
id: 1,
name: "Jane",
lastname: "Doe",
age: 25,
gender: "female",
city: "London"
},
{
id: 2,
name: "John",
lastname: "Doe",
age: 26,
gender: "male",
city: "London"
},
{
id: 3,
name: "James",
lastname: "Jones",
age: 30,
gender: "male",
city: "New York"
},
{
id: 4,
name: "Mary",
lastname: "Johnson",
age: 23,
gender: "female",
city: "Paris"
},
{
id: 5,
name: "Robert",
lastname: "Lee",
age: 44,
gender: "male",
city: "Berlin"
}
];
function LoadGrid() {
$("#grid").kendoGrid({
schema: {
model: {
fields: {
id: {
type: "number"
},
name: {
type: "string"
},
lastname: {
type: "string"
},
age: {
type: "number"
},
gender: {
type: "string"
},
city: {
type: "string"
}
}
}
},
columns: [{
title: "id",
field: "id",
width: 100,
locked: true
},
{
title: "First",
field: "name",
locked: true,
width: 150
},
{
title: "Last",
field: "lastname",
locked: true,
width: 150
},
{
title: "Age",
field: "age",
width: 100
},
{
title: "Gender",
field: "gender",
width: 100
},
{
title: "City",
field: "city",
width: 100
}
],
dataSource: {
data: ds
},
sortable: true
});
}
function EnableDragAndDropForGrid() {
let grid = $('#grid').data('kendoGrid');
grid.table.kendoSortable({
filter: ">tbody >tr",
hint: function(element) {
let table = $('<table style="width: 600px;" class="k-grid k-widget"></table>'),
hint;
table.append(element.clone());
table.css("opacity", 0.7);
return table;
},
cursor: "move",
placeholder: function(element) {
return $('<tr colspan="4" class="placeholder"></tr>');
},
change: function(e) {
let skip = grid.dataSource.skip(),
oldIndex = e.oldIndex + skip,
newIndex = e.newIndex + skip,
data = grid.dataSource.data(),
dataItem = grid.dataSource.getByUid(e.item.data("uid"));
grid.dataSource.remove(dataItem);
grid.dataSource.insert(newIndex, dataItem);
}
});
}
.k-grid tbody tr {
cursor: move;
}
.placeholder {
outline-style: dashed;
outline-width: 1px;
outline-color: red;
}
#grid {
width: 600px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2019.1.220/js/kendo.all.min.js"></script>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.common.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.rtl.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.silver.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.220/styles/kendo.mobile.all.min.css" />
<div id="grid"></div>
此问题的解决方案是
该行为的原因是具有锁定列的剑道 UI 网格创建了两个表,并且当前可排序小部件在保存非锁定内容的表上初始化。
要初始化在锁定表上的拖放,我们需要使用 lockedTable 元素。
如果您希望用户看到整行,可以通过查找具有相同 data-uid 的行从另一个表中获取相应的单元格
function EnableDragAndDropForGrid() {
let grid = $('#grid').data('kendoGrid');
console.log(grid)
grid.lockedTable.kendoSortable({
filter: ">tbody >tr",
hint: function(element) {
var unlockedPortion = grid.table.find("tr[data-uid=" + element.data("uid") + "]").children();
let table = $('<table style="width: 600px;" class="k-grid k-widget"></table>'),
hint;
table.append(element.clone().append(unlockedPortion));
table.css("opacity", 0.7);
return table;
},
cursor: "move",
placeholder: function(element) {
return $('<tr colspan="4" class="placeholder"></tr>');
},
change: function(e) {
let skip = grid.dataSource.skip(),
oldIndex = e.oldIndex + skip,
newIndex = e.newIndex + skip,
data = grid.dataSource.data(),
dataItem = grid.dataSource.getByUid(e.item.data("uid"));
grid.dataSource.remove(dataItem);
grid.dataSource.insert(newIndex, dataItem);
}
});
}
因此,我通过创建一个函数来解决此问题,该函数可以在创建具有锁定列的可拖动网格后调用。不幸的是,网格的 rowReorder 事件从未被调用。
喜欢这个:
let myGrid = $("#myGrid").kendoGrid({
reorderable: {
rows: true,
},
rowReorder: function(ev) {
// doesn't seem to work with locked columns.
},
// rest of options
}).data("kendoGrid");
//Optionally pass a callback function as the second parameter.
//It will get the same parameters as the rowReorder function should have gotten.
enableKendoGridLockedDND("#myGrid", reorderHappened);
function reorderHappened(e) {
console.log(e);
}
这是函数:
// You can pass a function as the second parameter which will be called on change.
// The on change function will receive information from the change event and
// pass it back as a parameter to the function you pass.
// Access it like myFunction(e).
function enableKendoGridLockedDND(gridElement, onChangeFunction) {
if (!gridElement) {
gridElement = ".k-grid";
}
let grid = $(gridElement).data("kendoGrid");
if (!grid.lockedTable) {
console.info("The function enableKendoGridLockedDND was called on a table without any locked columns");
return false;
}
let gridWidth = $(gridElement).width();
let lockedWidth = $(gridElement).find(".k-grid-header-locked").width() || 0;
let unlockedWidth = $(gridElement).find(".k-grid-header-wrap table").width() || 0;
let tableWidth = lockedWidth + unlockedWidth + 2;
let placeholderPosition = null;
grid.lockedTable.kendoSortable({
axis: "y",
filter: ">tbody >tr",
hint: function(element) {
let unlockedPortion = grid.table.find("tr[data-uid=" + element.data("uid") + "]").children();
let hint = $(`<div style="overflow: hidden; width: ${gridWidth}px;"><table style="background: whitesmoke; width: ${tableWidth}px;" class="k-grid k-widget"></table></div>`);
let colgroups = $(gridElement).find(".k-grid-header colgroup");
let colgroupWidths = [];
$.each(colgroups, function (index, group) {
$.each($(group).children(), function (index2, child) {
colgroupWidths.push($(child).css("width"));
});
});
hint.find("table").append(element.clone().append(unlockedPortion.clone()));
$.each(hint.find("td"), function (index, col) {
$(col).css("width", colgroupWidths[index]);
});
hint.css("opacity", 0.7);
return hint;
},
cursor: "move",
placeholder: function (element) {
var unlockedRow = grid.table.find("tr[data-uid=" + element.data("uid") + "]");
$(unlockedRow).before($(unlockedRow).clone().attr("data-uid", "").addClass("k-hover unlocked-placeholder"));
$(unlockedRow).hide();
let placeholder = element.clone();
$(placeholder).attr("data-uid", "");
return placeholder;
},
move: function (e) {
//Set positions
let lastPosition = placeholderPosition;
placeholderPosition = this.indexOf(this.placeholder);
let itemPosition = this.indexOf(e.item);
let targetPosition = this.indexOf(e.target);
//Get Elements
let unlockedDraggingRow = $(gridElement).find(".k-grid-content tr.unlocked-placeholder");
let targetElement = $(gridElement).find(".k-grid-content tr[data-uid=" + e.target.data("uid") + "]");
//Find direction of move
let movingUp = false;
if (lastPosition === null) {
if (itemPosition > targetPosition) {
movingUp = true;
}
} else {
if (lastPosition > placeholderPosition) {
movingUp = true;
}
}
//Move the unlocked row
if (movingUp) {
targetElement.before(unlockedDraggingRow);
} else {
targetElement.after(unlockedDraggingRow);
}
},
change: function (e) {
let skip = grid.dataSource.skip() || 0;
let newIndex = e.newIndex + skip;
let dataItem = grid.dataSource.getByUid(e.item.data("uid"));
grid.dataSource.remove(dataItem);
grid.dataSource.insert(newIndex, dataItem);
// Custom function to call
if (typeof onChangeFunction === "function") {
e.skip = skip;
e.newWithSkip = newIndex;
e.oldWithSkip = e.oldIndex + skip;
onChangeFunction(e);
}
},
start: function () {
placeholderPosition = null;
}
});
}
我还在这里发布了这个答案的一个版本:[Telerik Kendo UI Jquery Forum][https://www.telerik.com/forums/grid-with-locked-column-and-drag-and-drop]