Skip to content

fix: SelectAll selects all items even if unselectable due to Selectable in DataGrid's SelectColumn #3447

@runeterp

Description

@runeterp

🐛 Bug Report

When Selectable is set and multiple rows are not selectable, select all still selects every item in the Datagrid.

💻 Repro or Code Sample

<FluentDataGrid
    TGridItem="Test"
    Items="Data"
    OnRowClick="PrintSelected">
    <ChildContent>
        <SelectColumn
            TGridItem="Test"
            Selectable="@(test => test.Count > 2)" 
            SelectMode="DataGridSelectMode.Multiple" 
            SelectFromEntireRow="false" 
            @bind-SelectedItems="_selected"/>
        <PropertyColumn Property="@(t => t.Count)" Title="Count" Sortable="true"/>
    </ChildContent>
</FluentDataGrid>

@code
{
    private class Test
    {
        public int Count { get; init; }
    }

    private IQueryable<Test> Data { get; set; } = new List<Test>()
    {
        new Test { Count = 1 }, 
        new Test { Count = 2 },
        new Test { Count = 3 },
        new Test { Count = 4 },
        new Test { Count = 5 }
    }.AsQueryable();

    private IEnumerable<Test> _selected = new List<Test>();

    private void PrintSelected()
    { 
        Console.WriteLine(_selected.Count()); 
    }
}

🤔 Expected Behavior

When select is clicked, only the items that are deemed selectable by the Selectable function should be added to SelectedItems.

😯 Current Behavior

Currently all values are added to SelectedItems even if they are not selectable.

💁 Possible Solution

From looking through the code, the solution seems to be to add another check for if Selectable is set and if true do something like this _selectedItems.AddRange(InternalGridContext.Grid.Items?.Where(Selectable).ToArray() ?? InternalGridContext.Items); on the OnClickAllAsync method;

internal async Task OnClickAllAsync(MouseEventArgs e)
    {
        if (Grid == null || SelectMode != DataGridSelectMode.Multiple || SelectAllDisabled)
        {
            return;
        }

        // SelectAllChanged
        SelectAll = !(SelectAll == true);
        if (SelectAllChanged.HasDelegate)
        {
            await SelectAllChanged.InvokeAsync(SelectAll);
        }

        // SelectedItems
        _selectedItems.Clear();
        if (SelectAll == true)
        {
            _selectedItems.AddRange(InternalGridContext.Grid.Items?.ToArray() ?? InternalGridContext.Items);
        }

        if (SelectedItemsChanged.HasDelegate)
        {
            await SelectedItemsChanged.InvokeAsync(SelectedItems);
        }

        RefreshHeaderContent();
    }

🔦 Context

It simply adds items that are not applicable for selection, which means that backend calls can fail due to invalid data.

🌍 Your Environment

  • OS & Device: macOS Sequoia 15.3.1 on an M2 MacBook Air
  • Browser: Microsoft Edge
  • .NET and Fluent UI Blazor library Version: 8.0 and 4.11.5

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions