Automatically and Flexibly Persist Group Expand/Collapse State on Client Side (AJAX or client-side data)

6 posts, 0 answers
  1. Andre Light
    Andre Light avatar
    11 posts
    Member since:
    Apr 2010

    Posted 31 Mar 2015 Link to this post

    Requirements

    Telerik Product and Version

    Any version that includes RadGrid's GroupLoadMode="Client" functionality

    Supported Browsers and Platforms

    All modern browsers

    Components/Widgets used (JS frameworks, etc.)

    JQuery (Basic use only)
    Written using TypeScript, which can be compiled to JS here

    PROJECT DESCRIPTION 
    Finally: Preserve any RadGrid's group expand/collapse state automatically and entirely on the client, regardless of refresh method.  Supports AJAX refresh (server-side Rebind/DataBind), ClientDataSource, or any other client-side data binding method.

    Core Functionality
    Pass Grid Client ID to constructor.  You can then manually call methods to save/restore group state 100% on the client (when RadGrid.GroupLoadMode = Client).
    - Call SaveGrouping method on AJAX Request Start/before Client Data Source refresh.
    - Call RestoreGrouping method on AJAX Response End or after Client Data Source refresh.

    Parameters
    - saveGridScrollPosition
        * Default = True
        * This will save/restore the grid-specific scrolling position (scrollTop only) along with the group state.
        * Works when ClientSettings.Scrolling.AllowScroll = True

    - groupByExpression_SecondColumnDisplayName
        * If you use a standardized expression in the GroupByExpression for all columns (second column summary is always the same for all groupable columns), then enter the second column's display name so the group preservation will work even if the secondary summary data changes.
        * If you examine this code, you will see that minor adjustments could allow checking multiple second-column values (pass column names as Array<string>.

    - clientDataSource_AddEventHandlers
        * Default = False
        * Automatically save group state when using a Client Data Source.
        * Refinement suggestion: only save/restore for specific grid actions.

    - ajaxRefresh_AddEventHandlers
        * Default = False
        * Automatically save group state when using AJAX.
        * Refinement suggestion: only save/restore if a specific grid is refreshed.

    Implementation Example
    Add this code to a method that runs after your application has fully loaded--it should be executed only once after the page loads (if you're using AJAX, make sure it does not run after an AJAX postback response ends).  Remember, you can convert all TypeScript to JavaScript at the TS playground.

    Extender Initialization (TypeScript)
    var Grid_GroupStatePreservation: ClApps_Common.Extenders.Telerik.RadGrid.GroupStatePreservation.Core;
    function ApplicationLoaded(): void {
        var GroupStatePreservation_Options = new ClApps_Common.Extenders.Telerik.RadGrid.GroupStatePreservation.Options("** Grid Client ID, e.g. <%= Grid1.ClientID %> **");
        GroupStatePreservation_Options.groupByExpression_SecondColumnDisplayName = "Tickets";
        Grid_GroupStatePreservation = new ClApps_Common.Extenders.Telerik.RadGrid.GroupStatePreservation.Core(GroupStatePreservation_Options);
    }

    Preserve Group Expand State Manually
    You should Save and Restore groups when appropriate for your application.  For AJAX-refreshed grids, you'd want to save On Request Start and restore On Response End.  For client-side data sources, it might be best to save on grid command, and then restore on dataBound.  Using the options specified above, you could specify that the extender should apply those basic event handlers automatically or add additional automated event handlers to the extender to suit your needs.

    Here's an example to manually call the methods to save/restore group expand state:
    function RadAjaxManager1_requestStart(sender, eventArgs): void {
        Grid_GroupStatePreservation.SaveGrouping();
    }
    function RadAjaxManager1_responseEnd(sender, eventArgs): void {
        Grid_GroupStatePreservation.RestoreGrouping();
    }

    Please let me know if you have any questions or suggestions.
  2. Marin
    Admin
    Marin avatar
    1045 posts

    Posted 01 Apr 2015 Link to this post

    Hi Andre,

    Thank you for sharing your approach in the code library section on our site. It may prove helpful for other developers looking for similar implementation for their grids. We have updated your Telerik points as a token of gratitude.

    Essentially, a runnable sample demonstrating the actual functionality would be more convenient. Therefore, we have also attached a basic application. It should be noted, however, that this custom approach is intended primarily for the specific scenario of the author and any further enhancements are beyond the support scope of our team.

    Regards,
    Marin
    Telerik
     

    See What's Next in App Development. Register for TelerikNEXT.

     
  3. Andre Light
    Andre Light avatar
    11 posts
    Member since:
    Apr 2010

    Posted 01 Apr 2015 in reply to Marin Link to this post

    Marin, thank you very much for creating a sample application and also providing improvement suggestions.

    I've updated Marin's sample application to fix some minor issues and functionality omissions:

    - Added TypeScript definition files (jquery.d.ts, microsoft.ajax.d.ts, and Telerik.Web.UI.d.ts) so the sample would build with TypeScript.
    - Added script reference to generated JS file.
    - Added group summary column and GroupByExpression to demonstrate groupByExpression_SecondColumnDisplayName functionality, which enable group state preservation even when including group aggregates that will change as the data is updated.
    - Improved groupByExpression_SecondColumnDisplayName option so it is applied only if the aggregate value is present.
    - Fixed some minor issues in the extender class (proper saveGridScrollPosition option implementation; RestoreGrouping will proceed if there are only collapsed group entries, i.e. all groups are collapsed).
    - Consolidated code and added element index information in case you want to track the group element index in addition to the group text (not recommended).

    Known Limitation: Does not work with Blank or Duplicate Group Names
    This extender depends upon the presence of unique group display text, which is a design choice that allows it to restore even as the row counts and group positions change.  However, that approach has a limitation: it will not work if you have groups without any text, or if you have duplicate group display names.  Those scenarios seem to be non-intuitive ways of displaying grouped data, but if it impacts you, you can easily edit this extender by tracking the group element index while looping through all group rows--simply alter the GroupText value that's set in _get_GroupState__Obf like this:

    var GroupText__Obf = tdElement_NextSibling__Obf.innerText + "_" + elementIndex__Obf.toString();

    Here's the updated initialization and use code that matches the attached example:
    var Grid_GroupStatePreservation: ClApps_Common.Extenders.TelerikCustom.RadGrid.GroupStatePreservation.Core;
    function ApplicationLoaded(): void {
        var GroupStatePreservation_Options = new ClApps_Common.Extenders.TelerikCustom.RadGrid.GroupStatePreservation.Options("RadGrid1");
        GroupStatePreservation_Options.groupByExpression_SecondColumnDisplayName = "Random Number Sum";
        Grid_GroupStatePreservation = new ClApps_Common.Extenders.TelerikCustom.RadGrid.GroupStatePreservation.Core(GroupStatePreservation_Options);
    }
     
    function RadAjaxManager1_requestStart(sender, eventArgs): void {
        Grid_GroupStatePreservation.SaveGrouping();
    }
    function RadAjaxManager1_responseEnd(sender, eventArgs): void {
        Grid_GroupStatePreservation.RestoreGrouping();
    }

    Since the upload is limited to 2 MB, I could not upload a complete sample application like Marin, but I've uploaded the source changes so you can simply download Marin's sample, then download this sample and extract/merge with Marin's sample.

    Andre
  4. Andre Light
    Andre Light avatar
    11 posts
    Member since:
    Apr 2010

    Posted 02 Apr 2015 in reply to Andre Light Link to this post

    More changes in the attached after receiving more Telerik feedback:

    - Overhauled extender to improve support for nested groups (determine the path to the nested group to ensure that nested group expand/collapse state is retained when the nested group names might be duplicated across parent groups but have a unique path name to each sub-group).
    - Removed the saveGridScrollPosition because that functionality is built in to the RadGrid (ClientSettings-Scrolling.SaveScrollPosition="true"):
    <ClientSettings>
        <Scrolling AllowScroll="true" ScrollHeight="400px" UseStaticHeaders="true"
                SaveScrollPosition="true" />
    </ClientSettings>

    - Added a new option to specify whether additional GroupByExpression aggregates should be stripped automatically.
    - Refactored and renamed for better clarity and maintainability.

    I think this extension is now at v0.7 :-)

    Please download the attached zip file that includes the changed files (remember, you will need to download Marin's original GroupStatePreservation.zip file to get the complete sample with Telerik binaries).  Here's the updated initialization/use example:
    var Grid_GroupStatePreservation: ClApps_Common.Extenders.TelerikCustom.RadGrid.GroupStatePreservation.Core;
    function ApplicationLoaded(): void {
        var GroupStatePreservation_Options = new ClApps_Common.Extenders.TelerikCustom.RadGrid.GroupStatePreservation.Options(
            "RadGrid1", true, "Random Number Sum");
        Grid_GroupStatePreservation = new ClApps_Common.Extenders.TelerikCustom.RadGrid.GroupStatePreservation.Core(
            GroupStatePreservation_Options);
    }
    $telerik.$(document).ready(function () {
        ApplicationLoaded();
    });
     
    function RadAjaxManager1_requestStart(sender, eventArgs): void {
        Grid_GroupStatePreservation.SaveGrouping();
    }
    function RadAjaxManager1_responseEnd(sender, eventArgs): void {
        Grid_GroupStatePreservation.RestoreGrouping();
    }
  5. Andre Light
    Andre Light avatar
    11 posts
    Member since:
    Apr 2010

    Posted 03 Apr 2015 in reply to Andre Light Link to this post

    Due to extensive ongoing changes, I've moved the source code for this extension to GitHub: https://github.com/alight-eskillz/telerik-extensions-aspnet-grid.

    All future changes will be updated there.

  6. Andre Light
    Andre Light avatar
    11 posts
    Member since:
    Apr 2010

    Posted 06 May 2015 in reply to Andre Light Link to this post

    Separated common code from ASP.Net RadGrid code and added a preliminary Kendo UI example (which reuses the common functionality with minor customizations).

    Updated GitHub URL.

Back to Top