havit / Havit.Blazor

Free Bootstrap 5 components for ASP.NET Blazor + optional enterprise-level stack for Blazor development (gRPC code-first, layered architecture, localization, auth, ...)
https://havit.blazor.eu
MIT License
477 stars 67 forks source link

[HxGridColumn] Parameter changes take effect after a roundtrip (eg. changing Visible=true|false) #705

Closed Genmutant closed 1 month ago

Genmutant commented 9 months ago

I'm trying to optionally Hide some HxGridColumns, with the Visibility bound to a HxSwitch. The problem I have is that the first time the Checked-State is changed, the column visibility is not changed. Any Checked-Change afterwards triggers a visibilty change, but it is out of sync with the bound value.

I'm using a current dotnet 8 Blazor with InteractiveServer Rendering. Here is my example, which doesn't work:

@page "/TestPage"

@rendermode InteractiveServer

<h3>TestPage</h3>
<HxSwitch @bind-Value="ShowAllColumns" Text="Show All Columns"></HxSwitch>
<HxCheckbox @bind-Value="ShowAllColumns" Text="Show All Columns"></HxCheckbox>

<HxGrid TItem="RowEntry" DataProvider="GetGridData" >
    <Columns>
        <HxGridColumn HeaderText="FirstColumn" ItemTextSelector="entry => entry.FirstColumn" Visible="ShowAllColumns"></HxGridColumn>
        <HxGridColumn HeaderText="SecondColumn" ItemTextSelector="entry => entry.SecondColumn"></HxGridColumn>
        <HxGridColumn HeaderText="ThirdColumn" ItemTextSelector="entry => entry.ThirdColumn" Visible="ShowAllColumns"></HxGridColumn>
    </Columns>
</HxGrid>

@code {
    [Parameter] public bool ShowAllColumns { get; set; }

    public record RowEntry(string FirstColumn, string SecondColumn, string ThirdColumn);

    private Task<GridDataProviderResult<RowEntry>> GetGridData(GridDataProviderRequest<RowEntry> request) {
        return Task.FromResult(request.ApplyTo(new[] {
            new RowEntry("A1", "B1", "C1"),
            new RowEntry("A2", "B2", "C2"),
            new RowEntry("A3", "B3", "C3"),
        }));
    }
}

It seems that the IsVisible state change is only reflected after the column-visibility check is already done in GetColumnsToRender.

hakenr commented 8 months ago

I successfully reproduced the issue reported (BlazorAppTest/HxGrid_Issue705_Test). 2024-01-08_21-15-27

It is a bug (possibly caused by the design of HxGrid where the columns are rendered first to allow their usage as templates for the grid rows).

For now, as a simple workaround you can use this code to achieve the effect you expect:

<HxGrid TItem="RowEntry" DataProvider="GetGridData">
    <Columns>
        @if (ShowAllColumns)
        {
            <HxGridColumn Order="1" HeaderText="FirstColumn" ItemTextSelector="entry => entry.FirstColumn"/>
        }

        <HxGridColumn Order="2" HeaderText="SecondColumn" ItemTextSelector="entry => entry.SecondColumn" />

        @if (ShowAllColumns)
        {
            <HxGridColumn Order="3" HeaderText="ThirdColumn" ItemTextSelector="entry => entry.ThirdColumn" />
        }
    </Columns>
</HxGrid>

Please note the Order parameter, which ensures the right order of the columns if rendered conditionally.

cc @jirikanda

hakenr commented 8 months ago

(TBD: Consider marking the Visible parameter obsolete. Still the issue should be resolved as it obviously not only affect the Visible, but also other parameters of the HxGridColumn.)