Planned
Last Updated: 30 Apr 2021 12:24 by ADMIN
Scheduled for 3.0.0
Svetoslav
Created on: 01 Dec 2020 10:17
Category: Grid
Type: Feature Request
7
Expanded Items in the Grid State.

Hello everyone,

We created this Feature Request to gather feedback on the way the item expansion is working in the Grid state. Currently, you can expand any items with the ExpandedRows collection of int where you pass the indexes of the rows. 

Another option, which we are thinking of, is to provide a Collection<Model>. This would let you pass models, instead of indexes and the Grid would automatically expand those items. This approach would make the need to preserve the indexes redundant, which you should currently do when Filtering/Sorting and Grouping the items in the Grid.

We would appreciate your feedback on both approaches and which you think will be easier to use.

1 comment
ADMIN
Svetoslav Dimitrov
Posted on: 08 Dec 2020 09:50

Hello everyone,

I would like to offer a workaround solution for the time being. Below, I have provided some additional explanation on the current approach and what will change when this feature request is implemented. 

Current approach:

Currently, the Grid exposes a List<int> - ExpandedRows. In order to use features like sorting and filtering you should preserve the index/es (depending on the number of rows you would like to expand). In order to do that, you should use the OnRead event, which gives information on the current state of the data source (filtered/sorted).

@using Telerik.DataSource
@using Telerik.DataSource.Extensions

<TelerikGrid Data="@currentSalesTeamMembers"
             OnRowClick="@OnRowClickHandler"
             @ref="Grid"
             OnRead="@OnReadHandler"
             TotalCount="@Total"
             Sortable="true">
    <DetailTemplate>
        @{
            var employee = context as MainModel;
            <TelerikGrid Data="employee.Orders" Pageable="true" PageSize="5">
                <GridColumns>
                    <GridColumn Field="OrderId"></GridColumn>
                    <GridColumn Field="DealSize"></GridColumn>
                </GridColumns>
            </TelerikGrid>
        }
    </DetailTemplate>
    <GridColumns>
        <GridColumn Field="Id"></GridColumn>
        <GridColumn Field="Name"></GridColumn>
    </GridColumns>
</TelerikGrid>

@code {
    public TelerikGrid<MainModel> Grid { get; set; }
    public int Total { get; set; }
    List<MainModel> salesTeamMembers { get; set; }
    List<MainModel> currentSalesTeamMembers { get; set; } //implementation of OnRead

    public bool shouldPreventOnRead { get; set; }

    MainModel currentItem { get; set; } //need to save the selected item to determine its new index

    async Task OnReadHandler(GridReadEventArgs args)
    {
        var dataSourceResult = salesTeamMembers.ToDataSourceResult(args.Request);

        currentSalesTeamMembers = dataSourceResult.Data.Cast<MainModel>().ToList(); // this is the collection with the sorted items

        int currentIndexOfItem = currentSalesTeamMembers.IndexOf(currentItem);

        Total = dataSourceResult.Total;

        if (Grid != null && !shouldPreventOnRead)
        {
            await ExpandFromState(currentIndexOfItem);
        }

        shouldPreventOnRead = false;

        StateHasChanged();
    }

    async Task OnRowClickHandler(GridRowClickEventArgs args)
    {
        var item = args.Item as MainModel;

        int rowIndex = currentSalesTeamMembers.IndexOf(item);

        currentItem = currentSalesTeamMembers[rowIndex];

        await ExpandFromState(rowIndex);
    }

    async Task ExpandFromState(int rowIndex)
    {
        shouldPreventOnRead = true;

        var currentState = Grid.GetState();

        if (currentState.ExpandedRows.Contains(rowIndex))
        {
            currentState.ExpandedRows = new List<int>();
        }
        else
        {
            currentState.ExpandedRows = new List<int> { rowIndex };
        }

        await Grid.SetState(currentState);
    }

    protected override void OnInitialized()
    {
        salesTeamMembers = GenerateData();
    }

    private List<MainModel> GenerateData()
    {
        List<MainModel> data = new List<MainModel>();
        for (int i = 0; i < 5; i++)
        {
            MainModel mdl = new MainModel { Id = i, Name = $"Name {i}" };
            mdl.Orders = Enumerable.Range(1, 15).Select(x => new DetailsModel { OrderId = x, DealSize = x ^ i }).ToList();
            data.Add(mdl);
        }
        return data;
    }

    public class MainModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<DetailsModel> Orders { get; set; }
    }

    public class DetailsModel
    {
        public int OrderId { get; set; }
        public double DealSize { get; set; }
    }
}

After implementing this feature request:

This is not implemented yet, so this code snippet is not runnable, but its purpose is to demonstrate what the feature would be like.

<TelerikGrid Data="@salesTeamMembers"
             OnRowClick="@OnRowClickHandler"
             @ref="Grid"
             Sortable="true">
    <DetailTemplate>
        @{
            var employee = context as MainModel;
            <TelerikGrid Data="employee.Orders" Pageable="true" PageSize="5">
                <GridColumns>
                    <GridColumn Field="OrderId"></GridColumn>
                    <GridColumn Field="DealSize"></GridColumn>
                </GridColumns>
            </TelerikGrid>
        }
    </DetailTemplate>
    <GridColumns>
        <GridColumn Field="Id"></GridColumn>
        <GridColumn Field="Name"></GridColumn>
    </GridColumns>
</TelerikGrid>

@code {
    public TelerikGrid<MainModel> Grid { get; set; }
    List<MainModel> salesTeamMembers { get; set; }

    async Task OnRowClickHandler(GridRowClickEventArgs args)
    {
        var item = args.Item as MainModel;

        await ExpandFromState(item);
    }

    async Task ExpandFromState(MainModel row)
    {
        var currentState = Grid.GetState();

        if (currentState.ExpandedItems.Contains(row))
        {
            currentState.ExpandedItems = new List<MainModel>();
        }
        else
        {
            currentState.ExpandedItems = new List<MainModel>(row);
        }

        await Grid.SetState(currentState);
    }

    protected override void OnInitialized()
    {
        salesTeamMembers = GenerateData();
    }

    private List<MainModel> GenerateData()
    {
        List<MainModel> data = new List<MainModel>();
        for (int i = 0; i < 5; i++)
        {
            MainModel mdl = new MainModel { Id = i, Name = $"Name {i}" };
            mdl.Orders = Enumerable.Range(1, 15).Select(x => new DetailsModel { OrderId = x, DealSize = x ^ i }).ToList();
            data.Add(mdl);
        }
        return data;
    }

    public class MainModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<DetailsModel> Orders { get; set; }
    }

    public class DetailsModel
    {
        public int OrderId { get; set; }
        public double DealSize { get; set; }
    }
}

Regards,
Svetoslav Dimitrov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.