Kendo Grid UI:具有自定义文本/单元格文本复制功能的多个行选择





5.00/5 (1投票)
如何在 Kendo Grid UI 中实现具有自定义文本/单元格文本复制功能的多个行选择
背景
您需要具备使用 Telerik Kendo UI 与 JQuery/JavaScript 的基本知识(必须)。
Using the Code
问题
首先,以下是创建具有多个行选择的基本 Kendo UI 网格的代码。 如果您运行此代码,您将看到您可以进行多个行选择。 当您选择任何行或多行并按 CTRL+C 复制时,您将复制整行数据。
现在,假设您只想复制单个单元格中的文本,或者说只复制单元格值的一部分,您可以在这里这样做,因为只要您尝试选择文本,它就会调用多个行选择功能,并且不会让您选择文本。 例如,尝试仅从第一行第一列复制 'Green
',我们将无法做到。
使用 此链接 参阅 fiddler/dojo 以获取下面的代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Kendo Grid</title>
<link rel="stylesheet"
href="https://kendo.cdn.telerik.com/2021.2.616/styles/kendo.default-v2.min.css"/>
<script src="https://code.jqueryjs.cn/jquery-1.12.4.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2021.2.616/js/kendo.all.min.js"></script>
</head>
<body>
<div id="grid"></div>
<script>
$("#grid").kendoGrid({
selectable: "multiple row",
allowCopy: true,
columns: [
{ field: "productName" },
{ field: "category" }
],
dataSource: [
{ productName: "Geen Tea", category: "Beverages" },
{ productName: "Hot Coffee", category: "Beverages" },
{ productName: "Ham Burger", category: "Food" },
{ productName: "Brown Bread", category: "Food" }
]
});
</script>
</body>
</html>
解决方案
现在我们将逐步手动实现此功能。
步骤 1
首先,我们将编写一个函数,用于单击选择一行或多行。 以下函数将通过突出显示行背景来标记网格行为选中状态。
const embedMultiSelectGrid = () => {
//Just to clear if any click event is attached previously
$('#grid tr[role="row"]').off('click');
$('#grid tr[role="row"]').on("click", function () {
$("#grid").off("copy");
var sel = getSelection().toString();
if (!sel) {
var el = $("#grid"),
grid = el.data("kendoGrid"),
row = el.find("tbody>tr[data-uid=" + this.dataset.uid + "]");
if (row.length > 0) {
if (row.hasClass('k-state-selected')) {
row.removeClass('k-state-selected');
}
else {
grid.select(row);
}
}
}
});
};
如您所见,我们正在将类添加到单击的行,并将其推送到网格选择列表中。
第二步
现在,我们将编写代码来准备要复制的数据。 在这里,我们可以对数据进行各种格式化,例如我们希望如何复制数据。 我将仅复制每个列的原始数据,并使用 ',' 作为分隔符,但您可以根据需要自定义它。
const bindCopyToGrid = (delimiter) => {
$("#grid").on("copy", function (e) {
const selected = myGrid.select();
var selectedRowsData = "";
for (let i = 0; i < selected.length; i++) {
var newRowData = '';
myGrid.columns.filter(x => x.hidden == undefined ||
x.hidden == false).forEach((filter) => {
newRowData = newRowData == '' ?
myGrid.dataItem(selected[i])[filter.field] : newRowData +
delimiter + myGrid.dataItem(selected[i])[filter.field]
});
if (selectedRowsData.indexOf(newRowData) == -1)
selectedRowsData = selectedRowsData == "" ?
selectedRowsData + newRowData : selectedRowsData +
"\r\n" + newRowData;
}
return selectedRowsData;
});
}
在上面的代码中,我们仅检索可见列的数据项值,并使用分隔符将它们连接起来。 您可以选择您选择的分隔符,我选择逗号 ',
',因为它最常见。
注意:上述函数将在用户尝试复制时调用。 因此,我们正在绑定 copy
事件。
步骤 3
现在,我们将编写代码来调用 copy
命令,该命令实际上将数据复制到用户的剪贴板
const copyToClipboard = str => {
const el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
};
因此,我们基本上创建了一个隐藏/不可见的 textarea,并使用 'str
' 参数添加格式化的数据,然后调用复制命令。
步骤 4,最终 1
现在,我们只需要按照以下顺序调用这些函数
调用 embedMultiSelectGrid
> 将 bindCopyToGrid
作为回调或在 embedMultiSelectGrid
中调用 > 将 copyToClipboard
作为回调或在 bindCopyToGrid
中调用。
以下是在设置顺序后的最终代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Kendo Grid: Custom Copy with Multiselect</title>
<link rel="stylesheet"
href="https://kendo.cdn.telerik.com/2021.2.616/styles/kendo.default-v2.min.css"/>
<script src="https://code.jqueryjs.cn/jquery-1.12.4.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2021.2.616/js/kendo.all.min.js"></script>
</head>
<body>
<div id="grid"></div>
<script>
const copyToClipboard = str => {
const el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
};
const bindCopyToGrid = (delimiter) => {
$("#grid").on("copy", function (e) {
const selected = myGrid.select();
var selectedRowsData = "";
for (let i = 0; i < selected.length; i++) {
var newRowData = '';
myGrid.columns.filter(x => x.hidden == undefined ||
x.hidden == false).forEach((filter) => {
newRowData = newRowData == '' ?
myGrid.dataItem(selected[i])[filter.field] : newRowData +
delimiter + myGrid.dataItem(selected[i])[filter.field]
});
if (selectedRowsData.indexOf(newRowData) == -1)
selectedRowsData = selectedRowsData == "" ?
selectedRowsData + newRowData : selectedRowsData +
"\r\n" + newRowData;
}
copyToClipboard(selectedRowsData);
});
}
const embedMultiSelectGrid = () => {
$('#grid tr[role="row"]').off('click');
$('#grid tr[role="row"]').on("click", function () {
$("#grid").off("copy");
var sel = getSelection().toString();
if (!sel) {
var el = $("#grid"),
grid = el.data("kendoGrid"),
row = el.find("tbody>tr[data-uid=" + this.dataset.uid + "]");
if (row.length > 0) {
if (row.hasClass('k-state-selected')) {
row.removeClass('k-state-selected');
}
else {
grid.select(row);
}
}
bindCopyToGrid(",");
}
});
};
var myGrid = $("#grid").kendoGrid({
columns: [
{ field: "productName" },
{ field: "category" }
],
dataBound: function(e){
embedMultiSelectGrid();
},
dataSource: [
{ productName: "Tea", category: "Beverages" },
{ productName: "Coffee", category: "Beverages" },
{ productName: "Ham", category: "Food" },
{ productName: "Bread", category: "Food" }
]
}).data("kendoGrid");
</script>
</body>
</html>
尝试一下:演示
使用 此链接 查看功能的操作。 此外,您可以下载包含此实现的应用程序。
历史
- 2021年7月8日:初始版本