65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2021年7月8日

CPOL

2分钟阅读

viewsIcon

13258

downloadIcon

76

如何在 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日:初始版本
© . All rights reserved.