Telerik Kendo UI 网格:分组和排序仍然存在 grid.refresh() 但折叠的组被扩展;如何保持状态

Tim*_*Tim 5 grid grouping datasource refresh kendo-ui

与监视动态变化数据的“仪表板”应用程序中的网格一样,我的(Telerik)Kendo UI 网格每隔 60 秒定期刷新一次新数据:

grid.dataSource.data(freshData);
grid.refresh();  // have been informed this refresh may not be necessary
Run Code Online (Sandbox Code Playgroud)

架构不会更改,但数据集中可能会显示一些新行,而有些可能已被删除。

虽然grid.refresh()分组保持不变,排序状态也被保留,但任何折叠的组都会被展开。

问题:如何保留(或恢复)组的展开/折叠状态(因此,专注于其他组折叠的特定展开组的用户不会因每个组重新展开的定期更新而感到不便/沮丧)默认)?

编辑:一些 Winforms 网格提供了一种在刷新数据之前“拍摄”组展开/折叠状态的快照的方法,然后在数据源刷新后重新应用该状态。如果 Kendo UI 网格中的组标题行具有 UID(在刷新后仍然存在),则可以完成。 但请参阅下面不涉及持久 UID 的建议方法。

用例:这是此功能的典型用例,但有些戏剧性。疾病控制中心正在按城市监测特定流感病毒株的实时爆发情况。每 15 秒刷新一次数据集。他们目前正专注于洛杉矶,并扩大了这座城市,而其他城市则崩溃了。如果整个网格每 15 秒扩大一次,就会激怒 CDC 的医生,他们进去掐死程序员,然后回家打高尔夫球,洛杉矶的每个人都屈服了。剑道真的要为那场灾难负责吗?

可能的功能增强建议:忽略我对上述 UID 的建议。这里有一个更好的方法。网格有

<div class="k-group-indicator" data-field="{groupedByDataFieldName}">
    ...
</div>
Run Code Online (Sandbox Code Playgroud)

现在,如果那个 k-group-indicator div 可以包含一个不同值的列表,data-field每个键的关联数据是相应部分的展开/折叠状态,那么就可以在创建之前将该列表保存到缓冲区中调用 dataSource.data( someNewData) 方法,然后在监听 dataBound 事件的事件处理程序中,可以重新应用那些展开状态。要找到分组值的相应分组部分,如果k-grouping-row可以有一个名为的属性group-data-value来保存特定分组部分的分组值,例如“销售”或“营销”,如果按数据分组,那将非常有帮助-字段称为部门。

<div class="k-group-indicator" data-field="dept" data-title="Dept" data-dir="asc">
       ...
   <div class="k-group-distinct-values">
     <div group-data-value="Sales" aria-expanded="false" />
     <div group-data-value="Events Planning" aria-expanded="true" />
   </div>  
</div>
Run Code Online (Sandbox Code Playgroud)

然后在k-grouping-row<tr class="k-grouping-row" group-data-value="Sales">

Cod*_*ike 4

这是可以理解的,这不是一个内置功能。它非常复杂,因为如果您有嵌套分组,则必须记住它所在的层次结构中的每个折叠组。由于项目将移入和移出数据源,因此跟踪起来会很痛苦。


也就是说,这是一种非常黑客的方法来完成你想要的事情,只要你不要变得太复杂。它只是使用该groupHeaderTemplate属性向每个分组行添加 UID。我只是使用列名 + 值作为 UID,如果您进入多个分组,这在技术上是错误的,但对于一个示例来说已经足够了。

从那里,在刷新之前,您可以从 Kendo 现在拥有的 ARIA 属性中找到折叠的组(旁注,您必须使用 2012 年第三季度才能实现此功能)。然后向下钻取并获取模板添加的 UID。

刷新后,您可以找到具有匹配 UID 的行,并将它们传递给网格.collapseGroup()函数以重新折叠它。

这是一个正在运行的 jsFiddle 演示了这一点。

复制/粘贴 jsFiddle 中的代码(请注意,我只在“城市”列上设置模板,因此在此示例中只有“城市”列将保留分组折叠!)

HTML:

<button id="refresh">Refresh</button>
<div id="grid" style="height: 380px"></div>
Run Code Online (Sandbox Code Playgroud)

JavaScript:

var _getCollapsedUids = function () {
    var collapsedUids = [];
    $("#grid .k-grouping-row span[data-uid]")
        .each(function(idx, item) {
            if($(item)
               .closest(".k-grouping-row")
               .children("td:first")
               .attr("aria-expanded") === "false") {
                collapsedUids.push($(item).data("uid"));
            }
        }
    );
    return collapsedUids;
};

var _collapseUids = function (grid, collapsedUids) {
    $("#grid .k-grouping-row span[data-uid]")
        .each(function(idx, item) {
            if($.inArray($(item).data("uid"), collapsedUids) >= 0) {
                console.log("collapse: " + $(item).data("uid"))
                grid.collapseGroup($(item).closest("tr"));
            }
        }
    );
};

var refresh = function () {
    var collapsedUids = _getCollapsedUids();
    var grid = $("#grid").data().kendoGrid;
    grid.dataSource.data(createRandomData(50));
    _collapseUids(grid, collapsedUids);
};

$("#refresh").click(refresh);

$("#grid").kendoGrid({
    dataSource: {
        data: createRandomData(50),
        pageSize: 10
    },
    groupable: true,
    sortable: true,
    pageable: {
        refresh: true,
        pageSizes: true
    },
    columns: [ {
            field: "FirstName",
            width: 90,
            title: "First Name"
        } , {
            field: "LastName",
            width: 90,
            title: "Last Name"
        } , {
            width: 100,
            field: "City",
            groupHeaderTemplate: '<span data-uid="City-#=value#">#= value #</span>'
        } , {
            field: "Title"
        } , {
            field: "BirthDate",
            title: "Birth Date",
            template: '#= kendo.toString(BirthDate,"dd MMMM yyyy") #'
        } , {
            width: 50,
            field: "Age"
        }
    ]
});
Run Code Online (Sandbox Code Playgroud)

就我个人而言,我根本不喜欢这个解决方案。它太 hacky 了,并且需要太多的 DOM 遍历。然而,如果不重新实现网格小部件,我想不出更好的方法来做到这一点。也许它足以满足您想要完成的任务,或者给您一个更好的想法。


最后一点;我检查了 Kendo UI 源代码,它似乎没有跟踪哪些分组被展开/折叠。他们所做的事情与我对 aria 属性所做的类似,但改为检查驱动图标状态的类:

            if(element.hasClass('k-i-collapse')) {
                that.collapseGroup(group);
            } else {
                that.expandGroup(group);
            }
Run Code Online (Sandbox Code Playgroud)

如果您没有使用 Kendo 2012 Q3 并且无法使用 aria-expanded 属性,您可以更改代码以检查图标类。