Telerik Kendo用户界面网格:分组和排序生存grid.refresh()但折叠的组会扩展;如何保持状态 [英] Telerik Kendo UI grid: grouping and sorting survive grid.refresh() but collapsed groups get expanded; how to preserve state

查看:762
本文介绍了Telerik Kendo用户界面网格:分组和排序生存grid.refresh()但折叠的组会扩展;如何保持状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如仪表板应用程序中用于监视动态变化数据的网格的典型情况,我的(Telerik)Kendo UI网格每隔60秒定期刷新一次新数据:

grid.dataSource.data(freshData);
grid.refresh(); //已被告知此刷新可能不是必需的

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

尽管 grid.refresh()分组完好无损,排序状态也保留,任何折叠的组都会扩展。问题:如何保留(或恢复)组的展开/折叠状态(因此,关注特定展开组并使其他组折叠的用户不会感到不便/受到每个组默认重新扩展的定期更新的影响?)?编辑:一些WinForms网格提供了一种在刷新数据之前对组展开/折叠状态拍摄快照的方法,然后在数据源刷新后重新应用该状态。 如果Kendo UI网格中的组标题行具有UID(在刷新后仍然存在),则可以完成。但请参阅下面的建议方法,其中不涉及持久性UID。



用例:
这是一个典型的,如果这个特性有点戏剧性的用例。按疾病控制中心正在按城市监测特定流感病毒株的实时暴发。每15秒刷新一次数据集。他们恰好在洛杉矶集中精力,让这个城市扩大,其他城市崩溃。如果整个网格每隔15秒扩展一次,它就会让CDC的医生气死,然后他们进入并扼杀程序员,然后他们回家打高尔夫球,洛杉矶的每个人都屈服了。 Kendo是否真的想要为这场灾难负责?

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

 < div class =k-group-indicator数据字段= {} groupedByDataFieldName > 
...
< / div>

现在,如果该k-group-indicator div可以包含<$ $的不同值的列表c $ c> data-field ,每个键的关联数据都是相应部分的展开/折叠状态,那么在调用dataSource之前,可以将该列表保存到缓冲区。 data(someNewData)方法,然后在侦听dataBound事件的事件处理程序中,可以重新应用这些展开状态。要找到分组值的相应分组部分,如果 k-grouping-row 可以具有名为 group-data的属性-value ,它保存特定分组部分的分组值,例如销售或市场营销,如果是由一个名为Department的数据字段进行分组的话。


$ b

  < div class =k-group-indicatordata-field =deptdata-title =Deptdata-dir =asc> 
...
< div class =k-group-distinct-values>
< div group-data-value =Salesaria-expanded =false/>
< div group-data-value =活动计划aria-expanded =true/>
< / div>
< / div>

,然后在 k-grouping-row < tr class =k-grouping-rowgroup-data-value =Sales> >

解决方案

可以理解的是,这不是内置功能。它非常复杂,因为如果你有嵌套的分组,你将不得不记住它存在的层次结构中的每个折叠组。由于项目将移入和移出数据源,这将是一个很难追踪的问题。






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



从那里,在刷新之前,您可以从Kendo现在的ARIA属性中找到折叠组(注意,您必须使用2012 Q3才能正常工作)。然后深入挖掘并获取由模板添加的UID。



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



下面是一个可用的jsFiddle,它演示了这一点。



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

HTML:


$ b

< button id =refresh>刷新< / button>
< div id =gridstyle =height:380px>< / div>

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));
}
}
);
返回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);
$ b $(#grid)。kendoGrid({
dataSource:{
data:createRandomData(50),
pageSize:10
},
groupable:true,
sortable:true,
可分页:{
refresh:true,
pageSizes:true
},
列: [{
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
},{
字段:BirthDate,
标题:出生日期,
模板:'#= kendo.toString(BirthDate,dd MMMM yyyy)#'
},{
宽度:50,
字段: 年龄
}
]
});






我个人并不喜欢这个解决方案,所有。这太hacky和太多的DOM遍历。但是,如果没有重新实现网格小部件,我想不出有更好的方法来做到这一点。也许这对你正在努力完成的任务或给你一个更好的主意会是足够好的。




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

  if(element.hasClass('ki-collapse')){
that.collapseGroup(group);
} else {
that.expandGroup(group);如果您没有使用Kendo 2012 Q3,并且不能使用aria-展开属性,您可以更改代码来检查图标类。


As is typical for grids in a "dashboard" application that monitors dynamically changing data, my (Telerik) Kendo UI grid is refreshed with fresh data periodically, every 60 seconds:

grid.dataSource.data(freshData);
grid.refresh();  // have been informed this refresh may not be necessary

The schema does not change, but some new rows might show up in the dataset and some might have been removed.

Although the grid.refresh() leaves the groupings intact, and the sort state is also preserved, any collapsed groups get expanded.

QUESTION: How to preserve (or restore) the expanded/collapsed state of the groups (so a user focusing on a particular expanded group with the other groups collapsed is not inconvenienced/frustrated by the periodic updates in which every group gets re-expanded by default)?

EDIT: Some Winforms grids provide a way to "take a snapshot" of the group expand/collapse state before refreshing data, and then to reapply that state after the datasource refresh. If the group header rows in the Kendo UI grid had UIDs (that survived a refresh) it could be done. But see the suggested approach below that does not involve persistent UIDs.

USE CASE: Here is a typical if somewhat dramatic use case for this feature. Center for Disease Control is monitoring real-time outbreaks of a particular strain of flu, by city. Every 15 seconds the dataset is being refreshed. They happen to be focusing at the moment on Los Angeles and have that city expanded, and the other cities collapsed. If every 15 seconds the entire grid expands, it pisses off the doctors at the CDC and they go in and strangle the programmer and then they go home to play golf, and everyone in Los Angeles succumbs. Does Kendo really want to be responsible for that disaster?

POSSIBLE FEATURE ENHANCEMENT SUGGESTION: Ignore my suggestion about a UID above. Here's a better way. The grid has

<div class="k-group-indicator" data-field="{groupedByDataFieldName}">
    ...
</div>

Now, if that k-group-indicator div could contain a list of the distinct values of data-field with each key's associated data being the expanded/collapsed state of the corresponding section, it would then be possible to save that list to a buffer before making a call to the dataSource.data( someNewData) method, and then in the eventhandler listening for dataBound event, those expand states could be reapplied. To find the corresponding grouping section for the grouping value, it would be very helpful if the k-grouping-row could have a property called group-data-value which held the grouping value of the particular grouping section, e.g. "Sales" or "Marketing" if one were grouping by a data-field called Department.

<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>

and then in the k-grouping-row: <tr class="k-grouping-row" group-data-value="Sales">

解决方案

It is understandable that this isn't a built-in feature. It is pretty complicated because if you have nested groupings, you would have to remember each collapsed group in the hierarchy that it existed in. Since items will be moving in and out of the DataSource, this would be a pain to track.


That said, here is a very hackish way to accomplish what you want, as long as you don't get too complicated. It just uses the groupHeaderTemplate property to add a UID to each grouping row. I am just using the column name + value as the UID, which is technically wrong if you get into multiple groupings, but it is good enough for an example.

From there, before you refresh you can find the collapsed groups from the ARIA attribute that Kendo has now (side-note, you have to be using 2012 Q3 for this to work). Then drill down and get the UID that was added by the template.

After the refresh, you can find the rows with a matching UID and pass them to the grid's .collapseGroup() function to re-collapse it.

Here is a working jsFiddle that demonstrates this.

And the code from the jsFiddle copy/pasted in (please note that I only set the template on the City column, so only the City column will preserve grouping collapse in this example!):

HTML:

<button id="refresh">Refresh</button>
<div id="grid" style="height: 380px"></div>

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"
        }
    ]
});


Personally I don't really like this solution at all. It is way too hacky and way too much DOM traversal. However without re-implementing the grid widget I can't think of a better way to do it. Maybe it will be good enough for what you are trying to accomplish or give you a better idea.


One last note; I checked the Kendo UI source code and it does not appear to track which groupings are expanded/collapsed. They do something similar to what I did with the aria attribute, but instead check the class that drives the icon state:

            if(element.hasClass('k-i-collapse')) {
                that.collapseGroup(group);
            } else {
                that.expandGroup(group);
            }

If you are not using Kendo 2012 Q3 and can't use the aria-expanded attribute, you could change the code to check the icon class instead.

这篇关于Telerik Kendo用户界面网格:分组和排序生存grid.refresh()但折叠的组会扩展;如何保持状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆