Completed
Last Updated: 24 Apr 2026 13:13 by ADMIN
Neal
Created on: 23 Apr 2026 16:43
Category: UI for Blazor
Type: Feature Request
0
Create a control that works like an iOS or Android TableView
Requesting a data control that works like a UITableView in iOS or data lists in Android. List data with a push into an editor, etc. with animation. Options to push, show modal, etc. replicating standard data lists on mobile phones and tablets so we can create a UI that acts more like what they are accustomed to for data.
1 comment
ADMIN
Dimo
Posted on: 24 Apr 2026 13:13

Hi Neal,

You can achieve the desired functionality by combining several of our components like the AnimationContainer and the ListView. Here is a simple POC example:

https://blazorrepl.telerik.com/GqOeweFw59EV6kCM39

Your request is generally valid, but there is one major concern with it. It seems that your goal is to match the native mobile UI and UX. This means that the same component may need to look and behave differently on Android and iOS. Such an approach is currently outside our product strategy. We have developed such hybrid products and components in the past, but their low adoption ultimately brought the decision to discontinue them. I am not sure that the business environment has changed considerably for us to consider going back.

Of course, we can always revisit this topic in the future.

Here is the same code from the REPL example. Note that the CSS classes in the ListView Template rely on the Telerik CSS utilities stylesheet.

<div style="position: relative; height: 66vh; width: 50vw; margin: 1em; border: 1px solid var(--kendo-color-border); overflow: auto;">
    <TelerikAnimationContainer @ref="AnimationContainerRef1"
                            AnimationDuration="@AnimationDuration12"
                            AnimationType="@AnimationType1"
                            Height="auto"
                            Left="0"
                            Top="0"
                            Width="100%">
        <TelerikListView Data="@ListItems1">
            <Template>
                @{ var dataItem = (ListItem)context; }
                <div class="list-item k-m-sm k-px-sm k-py-sm k-d-flex k-justify-content-between k-align-items-center k-rounded-md"
                     @onclick="@(() => GoTo2(dataItem.Id))">
                    <span>@dataItem.Text</span>
                    <TelerikSvgIcon Icon="@SvgIcon.ChevronRight" />
                </div>
            </Template>
        </TelerikListView>
    </TelerikAnimationContainer>

    <TelerikAnimationContainer @ref="AnimationContainerRef2"
                            AnimationDuration="@AnimationDuration12"
                            AnimationType="@AnimationType2"
                            Height="auto"
                            Left="0"
                            Top="0"
                            Width="100%">
        <TelerikListView Data="@ListItems2.Where(li => li.ParentId == SelectedRootItemId)">
            <Template>
                @{ var dataItem = (ListItem)context; }
                <div class="list-item k-m-sm k-px-sm k-py-sm k-d-flex k-justify-content-between k-align-items-center k-rounded-md"
                     @onclick="@GoTo1">
                    <span>@dataItem.Text</span>
                </div>
            </Template>
        </TelerikListView>
    </TelerikAnimationContainer>
</div>

<style>
    .list-item {
        background: var(--kendo-color-base);
        cursor: pointer;
    }
    .list-item:hover {
        background: var(--kendo-color-base-hover);
    }
</style>

@code {
    #nullable enable

    private TelerikAnimationContainer? AnimationContainerRef1;
    private AnimationType AnimationType1 { get; set; } = AnimationType.None;
    private TelerikAnimationContainer? AnimationContainerRef2;
    private AnimationType AnimationType2 { get; set; } = AnimationType.SlideLeft;
    private int AnimationDuration12 { get; set; }

    private List<ListItem> ListItems1 { get; set; } = new();
    private List<ListItem> ListItems2 { get; set; } = new();

    private int SelectedRootItemId { get; set; }

    private async Task GoTo2(int rootItemId)
    {
        SelectedRootItemId = rootItemId;

        if (AnimationContainerRef1 is not null && AnimationContainerRef2 is not null)
        {
            await AnimationContainerRef2.ShowAsync();
            await Task.Delay(1);
            await AnimationContainerRef1.HideAsync();
        }
    }

    private async Task GoTo1()
    {
        if (AnimationContainerRef1 is not null && AnimationContainerRef2 is not null)
        {
            await AnimationContainerRef1.ShowAsync();
            await Task.Delay(1);
            await AnimationContainerRef2.HideAsync();
        }
    }

    private int LastId { get; set; }

    protected override void OnInitialized()
    {
        ListItems1 = new List<ListItem>();
        ListItems2 = new List<ListItem>();

        for (int i = 1; i <= 48; i++)
        {
            int rootItemId = ++LastId;
            ListItems1.Add(new ListItem()
            {
                Id = rootItemId,
                Text = $"Root Item {i}",
                Category = $"Category {i % 6 + 1}"
            });

            for (int j = 1; j <= 7; j++)
            {
                ListItems2.Add(new ListItem()
                {
                    Id = ++LastId,
                    ParentId = rootItemId,
                    Text = $"Child Item {i}-{j}"
                });
            }
        }

        base.OnInitialized();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            if (AnimationContainerRef1 is not null)
            {
                await AnimationContainerRef1.ShowAsync();
                await Task.Delay(1);
                AnimationType1 = AnimationType.SlideRight;
                AnimationDuration12 = 300;
            }
        }

        await base.OnAfterRenderAsync(firstRender);
    }

    public class ListItem
    {
        public int Id { get; set; }
        public int? ParentId { get; set; }
        public string Text { get; set; } = string.Empty;
        public string Category { get; set; } = string.Empty;
    }
}

 

Regards,
Dimo
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.