TreeList, restore previously expanded items after redirect

1 Answer 24 Views
TreeList
Diego
Top achievements
Rank 1
Diego asked on 24 Oct 2025, 03:14 PM | edited on 24 Oct 2025, 03:17 PM

Hi,

I need to restore the expanded state of a RadTreeList after a redirect. I am storing the expanded items in Session before the redirect. However, server-side expansion only expands the root, not the child items.

Can someone share a JavaScript example or approach to fully expand all previously expanded nodes after a redirect using the stored session data? Or maybe provide a better example on Server Side

Thanks!


This is the example I was using on server side, but it only expands the root element


using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Telerik.Web.UI;

namespace Momentum.Mapp.WebApp.SysMgmt.Groups
{
    public partial class GroupMaintenanceServer : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                RadTreeList1.NeedDataSource += RadTreeList1_NeedDataSource;
            }
        }

        protected void RadTreeList1_NeedDataSource(object sender, TreeListNeedDataSourceEventArgs e)
        {
            RadTreeList1.DataSource = GetData();
        }

        protected void Page_PreRender(object sender, EventArgs e)
        {
            var expandedItems = RadTreeList1.Items
                .Where(i => i.Expanded)
                .Select(i => (int)i.GetDataKeyValue("ID"))
                .ToList();

            Session["ExpandedNodes"] = expandedItems;
        }

        protected void RadTreeList1_DataBound(object sender, EventArgs e)
        {
            if (Session["ExpandedNodes"] is List<int> expanded)
            {
                foreach (TreeListDataItem item in RadTreeList1.Items)
                {
                    int id = (int)item.GetDataKeyValue("ID");
                    if (expanded.Contains(id))
                        item.Expanded = true;
                }
            }
        }

        protected void RadTreeList1_ItemCommand(object sender, TreeListCommandEventArgs e)
        {
            if (e.CommandName == "EditItem" && e.Item is TreeListDataItem dataItem)
            {
                int id = (int)dataItem.GetDataKeyValue("ID");
                Response.Redirect($"EditPage.aspx?id={id}");
            }
        }

        // Ejemplo de datos simples
        private DataTable GetData()
        {
            var dt = new DataTable();
            dt.Columns.Add("ID", typeof(int));
            dt.Columns.Add("ParentID", typeof(int));
            dt.Columns.Add("Name", typeof(string));

            dt.Rows.Add(1, DBNull.Value, "Continents");
            dt.Rows.Add(2, 1, "Asia");
            dt.Rows.Add(3, 1, "Europe");
            dt.Rows.Add(4, DBNull.Value, "Oceans");
            dt.Rows.Add(5, 4, "Pacific");
            dt.Rows.Add(6, 4, "Atlantic");

            return dt;
        }

     }
}

1 Answer, 1 is accepted

Sort by
0
Vasko
Telerik team
answered on 29 Oct 2025, 10:38 AM

Hi Diego,

You can use the RadPersistenceFramework to automatically save and restore the expanded state. This approach requires less manual handling and works across page reloads and redirects.

 The Persistence Framework can be used on the following TreeList properties. For more information, please take a look at the WebForms PersistenceFramework Demo.

    Regards,
    Vasko
    Progress Telerik

    Your perspective matters! Join other professionals in the State of Designer-Developer Collaboration 2025: Workflows, Trends and AI survey to share how AI and new workflows are impacting collaboration, and be among the first to see the key findings.
    Start the 2025 Survey
    Diego
    Top achievements
    Rank 1
    commented on 29 Oct 2025, 07:01 PM

    hi Vasko

    In the example you provided it uses RadTreeView and I'm using RadTreeList which can not be used in RadPersistenceManager

    Do you have any other example using RadTreeList and expanding saved states in client side. We don't want postbacks for saving IDs when the user expands or collapse.

    Thanks,
    Diego
    Vasko
    Telerik team
    commented on 30 Oct 2025, 06:11 AM

    Hi Diego,

    The example shared demonstrates the base functionalities of the  RadPersistenceFramework, which can be used with the TreeList's properties as well:

    Regards,
    Vasko
    Progress Telerik

    Diego
    Top achievements
    Rank 1
    commented on 30 Oct 2025, 11:42 AM | edited

    hi Vasko, thanks for your answer.

    I tried the demo with RadTreeView and works correctly, however I tried to do almost the same in RadTreeList and didn't load the state after saving.

    I attached an example, would you be so kindful to update it accordingly? By the way, would be very helpful if we together can find a solution working directly on client side.

    Thank you so much, I really appreciate your help

    Thank you so much,
    Diego


    Diego
    Top achievements
    Rank 1
    commented on 30 Oct 2025, 06:45 PM

    In addition to the previous comment, I feel like I have a bug in 
    item.get_expanded(), for item ID=8, expanded = true, but if you see the picture, 8 is a child of item 7 and it's not expanded, value should be false., the same happens with value = 4 

    Moreover, is it possible to trigger an event when the user expands or collapse, or the only way to achive this behavior in javascript is "clicking a row" ?

    Thanks

    Vasko
    Telerik team
    commented on 03 Nov 2025, 06:43 AM

    Hi Diego,

    Please note that the TreeList does not provide built-in client-side events for expand/collapse actions. To achieve your goal of saving and restoring expanded state using client-side code and localStorage, you need to use the RadTreeList client-side API and custom JavaScript logic.

    Below you can find a basic example of saving the expanded indexes inside local storage and expanding the TreeList items based on the ID:

    <telerik:RadTreeList ID="RadTreeList1" runat="server"
        DataKeyNames="ID"
        ClientDataKeyNames="ID"
        ParentDataKeyNames="ParentID"
        AutoGenerateColumns="false"
        OnNeedDataSource="RadTreeList1_NeedDataSource"
        ExpandCollapseMode="Client">
        <ClientSettings>
        </ClientSettings>
        <Columns>
            <telerik:TreeListBoundColumn DataField="ID" HeaderText="ID" UniqueName="ID" />
            <telerik:TreeListBoundColumn DataField="Name" HeaderText="Nombre" UniqueName="Name" />
            <telerik:TreeListBoundColumn DataField="Description" HeaderText="Descripción" UniqueName="Description" />
        </Columns>
        <ClientSettings>
            <ClientEvents OnTreeListCreated="onTreeListCreated" />
        </ClientSettings>
    </telerik:RadTreeList>
    

    function onTreeListCreated(sender, args) {
        setTimeout(() => {
            let expandedIds = getSavedExpandedIds();
            let items = sender.get_dataItems();
    
            for (let i = 0; i < items.length; i++) {
                let item = items[i];
                let id = item.get_dataKeyValue("ID");
    
                if (expandedIds.includes(id)) {
                    item.toggleExpandCollapse();
                }
            }
        }, 10)
    
        let gridElement = sender.get_element();
        gridElement.addEventListener("click", function (e) {
            let target = e.target;
    
            let hasClickedIcon = target.classList.contains("rtlExpandIcon") || target.classList.contains("rtlCollapseIcon");
    
            if (hasClickedIcon) {
                let item = sender.getContainerItem(target);
                let id = item.get_dataKeyValue("ID");
                let expandedIds = getSavedExpandedIds();
    
                // Wait a bit for expand/collapse state to update
                setTimeout(() => {
                    if (item.get_expanded()) {
                        if (!expandedIds.includes(id)) {
                            expandedIds.push(id);
                        }
                    } else {
                        expandedIds = expandedIds.filter(x => x !== id);
                    }
                    saveExpandedIds(expandedIds);
                }, 50);
            }
        });
    }
    
    const EXPANDED_KEY = "key";
    
    function getSavedExpandedIds() {
        let data = localStorage.getItem(EXPANDED_KEY);
        return data ? JSON.parse(data) : [];
    }
    
    function saveExpandedIds(ids) {
        localStorage.setItem(EXPANDED_KEY, JSON.stringify(ids));
    }

    protected void RadTreeList1_NeedDataSource(object sender, TreeListNeedDataSourceEventArgs e)
    {
        RadTreeList1.DataSource = GetData();
    }
    
    public DataTable GetData()
    {
        DataTable table = new DataTable();
        table.Columns.Add("ID");
        table.Columns.Add("ParentID");
        table.Columns.Add("Name");
        table.Columns.Add("Description");
    
        table.Rows.Add(new String[] { "1", null, "World_Continents", "Continents" });
        table.Rows.Add(new String[] { "2", null, "World_Oceans", "Oceans" });
    
        table.Rows.Add(new String[] { "3", "1", "Asia", "Asia" });
        table.Rows.Add(new String[] { "4", "1", "Africa", "Africa" });
        table.Rows.Add(new String[] { "5", "1", "Australia", "Australia" });
        table.Rows.Add(new String[] { "6", "1", "Europe", "Europe" });
        table.Rows.Add(new String[] { "7", "1", "North_America", "North America" });
        table.Rows.Add(new String[] { "8", "1", "America_Latina", "America Latina" });
        table.Rows.Add(new String[] { "9", "8", "Paises", "Paises" });
        table.Rows.Add(new String[] { "10", "9", "Argentina", "Argentina" });
        table.Rows.Add(new String[] { "11", "9", "Uruguay", "Uruguay" });
        table.Rows.Add(new String[] { "12", "9", "Chile", "Chile" });
    
        table.Rows.Add(new String[] { "13", "2", "Arctic_Ocean", "Arctic Ocean" });
        table.Rows.Add(new String[] { "14", "2", "Atlantic_Ocean", "Atlantic Ocean" });
        table.Rows.Add(new String[] { "15", "2", "Indian_Ocean", "Indian Ocean" });
        table.Rows.Add(new String[] { "16", "2", "Pacific_Ocean", "Pacific Ocean" });
    
        return table;
    }

    Note that since the ExpandMode is set to Client, you will need to use the setTimeout() function to wait a small amount of time in order to trigger the expand of the TreeList items

    Regards,
    Vasko
    Progress Telerik

    Diego
    Top achievements
    Rank 1
    commented on 04 Nov 2025, 02:26 PM

    i was able to fix that out using your last example.

    Thank you so much!

    Diego
    Tags
    TreeList
    Asked by
    Diego
    Top achievements
    Rank 1
    Answers by
    Vasko
    Telerik team
    Share this question
    or