Completed
Last Updated: 19 Jan 2022 11:36 by ADMIN
Chris
Created on: 12 Jan 2022 16:40
Category: UI for Blazor
Type: Feature Request
0
Treeview multi select with single click

In order to be able to easily work on mobile (tablet) and desktop browsers using touch it would be great if tree view supported multi select through a single click to select and click to unselect option without the need to hold down the ctrl key or anything like that

This can be worked around currently implementing a TreeView template and then the OnClick event to allow custom tracking of selected and unselected items but this feels like a common enough requirement for touch support that it would be great to support out of the box with the control

1 comment
ADMIN
Nadezhda Tacheva
Posted on: 19 Jan 2022 11:36

Hello Chris,

The TreeView follows the multiple items selection principles that our other components incorporate ( for example Grid, TreeList ). By design, multiple selection for all of them is possible through holding the Ctrl key. I agree with you with that for mobile usage it is indeed more useful to be able to select/deselect item on single action and to cover this scenario we have exposed support for CheckBox selection. While it provides a bit different UX from the standard selection by not adding the background highlight color on the selected node, this could be customized once the OnItemRender event is available, so you can add a custom CSS Class to the selected items to highlight them if desired.

If this approach does not match the desired result, one can of course configure the component to allow selection on item click. However, that would be a customization based on personal preferences rather than a built-in feature as it would interfere with the current component design.

That said, you can indeed achieve your desired result by handling the OnItemClick event of the TreeView and programmatically modifying the SelectedItems collection. You would not necessarily need a template for that, though. Similar example is available for the Grid in the Select or Deselect Grid Items on Row Click knowledge base article. As for the Treeview, the approach could be as follows:

<TelerikTreeView Data="@FlatData"
                 OnItemClick="@OnItemClickHandler"
                 SelectionMode="@TreeViewSelectionMode.Multiple"
                 SelectedItems="@SelectedItems"
                 SelectedItemsChanged="((IEnumerable<object> items) => SelectedItemsChangedHandler(items))">
</TelerikTreeView>

@code {
    public IEnumerable<TreeItem> SelectedItems { get; set; } = new List<TreeItem>();

    public List<TreeItem> FlatData { get; set; }

    //Handle the SelectedItemsChanged event and do not execute any logic in it, so you can override the built-in selection.
    void SelectedItemsChangedHandler(IEnumerable<object> data)
    {
    }

    //Handle the OnItemClick to modify the SelectedItems collection
    async Task OnItemClickHandler(TreeViewItemClickEventArgs args)
    {
        var currItem = args.Item as TreeItem;

        if (SelectedItems.Any(x => x.Id == currItem.Id))
        {
            SelectedItems = SelectedItems.Where(x => x.Id != currItem.Id);
        }
        else
        {
            SelectedItems = SelectedItems.Concat(new[] { currItem });
        }
    }

    #region Data Generation

    protected override void OnInitialized()
    {
        LoadFlatData();
    }

    private void LoadFlatData()
    {
        List<TreeItem> items = new List<TreeItem>();

        items.Add(new TreeItem()
        {
            Id = 1,
            Text = "Project",
            ParentId = null,
            HasChildren = true,
            Icon = "folder",
            Expanded = true
        });

        items.Add(new TreeItem()
        {
            Id = 2,
            Text = "Design",
            ParentId = 1,
            HasChildren = true,
            Icon = "brush",
            Expanded = true
        });
        items.Add(new TreeItem()
        {
            Id = 3,
            Text = "Implementation",
            ParentId = 1,
            HasChildren = true,
            Icon = "folder",
            Expanded = true
        });

        items.Add(new TreeItem()
        {
            Id = 4,
            Text = "site.psd",
            ParentId = 2,
            HasChildren = false,
            Icon = "psd",
            Expanded = true
        });
        items.Add(new TreeItem()
        {
            Id = 5,
            Text = "index.js",
            ParentId = 3,
            HasChildren = false,
            Icon = "js"
        });
        items.Add(new TreeItem()
        {
            Id = 6,
            Text = "index.html",
            ParentId = 3,
            HasChildren = false,
            Icon = "html"
        });
        items.Add(new TreeItem()
        {
            Id = 7,
            Text = "styles.css",
            ParentId = 3,
            HasChildren = false,
            Icon = "css"
        });

        FlatData = items;
    }
    #endregion

    #region Data Models
    public class GridDataModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int WorkingOn { get; set; }
    }

    public class TreeItem
    {
        public int Id { get; set; }
        public string Text { get; set; }
        public int? ParentId { get; set; }
        public bool HasChildren { get; set; }
        public string Icon { get; set; }
        public bool Expanded { get; set; }
    }
    #endregion
}

Having the above mentioned in mind, I am hereby marking the request as completed as the desired result could be achieved with the current component configuration.

Please let us know if any further questions appear.

Regards,
Nadezhda Tacheva
Progress Telerik

Learn about the important changes coming in UI for Blazor 3.0 in January 2022!