Event when deselect all

How can you tell when all rows have been cleared/deselected?

Workaround Not Applicable

Similar to this post, but I'm not using the checkbox, so that workaround is not applicable.

Failed Attempt

Instead, I attempt to use "RowDeselected" to check for a row count of zero.  Unfortunately, it returns a false positive when switching from one row to another.  Row #1 gets deselected for a brief moment before row #2 is selected, so for a split second, all rows are deselected.

That's not what we're checking for.  It appears the existing events "RowSelected" and "RowDeselected" may be inadequate to the task.

Sequence of Events

The following sequence of events demonstrates how all rows get deselected briefly when switching rows:

  1. Click row #1 to select.
  2. Click row #2 to switch selection to row #2.
  3. Click row #2 to deselect all.

Outputs:

RowSelecting: Currently no rows selected
RowSelected: Currently Row #1 selected
RowDeselecting: Currently Row #1 selected
RowDeselected: Currently no rows selected
OnDeselectAll
RowSelecting: Currently no rows selected
RowSelected: Currently Row #2 selected
RowDeselecting: Currently Row #2 selected
RowDeselected: Currently no rows selected
OnDeselectAll

OnDeselectAll gets reported twice, once when switching between rows (false positive), and again when all rows are truly deselected.

Use Case

We want to disable menu options that only appear when a row is selected.

Minimal Example

See attachment for a minimal example, in Home.razor.

Version Info

Syncfusion.Blazor 26.2.8

Blazor serverside project


Attachment: SyncfusionTest_6c6de381.zip


11 Replies

MS Monisha Saravanan Syncfusion Team August 12, 2024 10:48 AM UTC


Hi Stephen,


Greetings from Syncfusion.


Query: “We want to disable menu options that only appear when a row is selected.”


We would like to inform you that by default, if a row is selected while another row is already selected, the RowDeselected event will be triggered first, followed by the RowSelected event. We understand that your requirement is to enable the menu only when a row is selected in the DataGrid.


To address this, we have prepared a simple example based on your requirements. In this example, we demonstrate how to enable the menu when a record is selected in the DataGrid. Please check the attached sample and code snippet for your reference.


Sample:  https://blazorplayground.syncfusion.com/embed/BXVfDvCrhneROFch?appbar=true&editor=true&result=true&errorlist=true&theme=bootstrap5


Here in the below code the highlighted if part will be triggered only when it has selected row and the else part will be triggered when there is no rows selected in DataGrid.


 

<SfGrid ID="GridSizeNew" @ref="Grid" DataSource="@Orders">

    <GridSelectionSettings Type="SelectionType.Multiple" Mode="Syncfusion.Blazor.Grids.SelectionMode.Row"></GridSelectionSettings>

    <GridEvents TValue="Order"

                RowSelected="RowSelectedHandler"

                RowDeselected="RowDeselectedHandler"

                ></GridEvents>

 

</SfGrid>

@if (CurrentOrder)

 

{

    <div> Enable menu</div>

}

 

else

 

{

 

    <div>No records selected.</div>

 

}

@code {

 

   SfGrid<Order> Grid;

    public List<Order> Orders { get; set; }

    public bool CurrentOrder { get; set; } = false;

    public async Task RowSelectedHandler(RowSelectEventArgs<Order> args)

    {

 

        var rec = await Grid.GetSelectedRecordsAsync();

        if (rec.Count >= 1)

        {

 

            CurrentOrder = true;

        }

    }

    public async Task RowDeselectedHandler(RowDeselectEventArgs<Order> args)

    {

        var rec = await Grid.GetSelectedRecordsAsync();

 

        if (rec.Count == 0)

        {

            CurrentOrder = false;

        }

 

    }

}

 

 



If you face difficulties in implementing the above solution, then kindly get back to us with additional information about the issue faced.


Regards,

Monisha



SG Stephen Green August 12, 2024 02:43 PM UTC

Hi, Monisha, this was the first solution we tried.  The problem is, it also triggers when switching between rows.  There is a brief moment of time where no row is selected, and this impacts the GUI.

In our application, when you click among different rows, you see a slow "flicker" where the menu is first hidden, and then immediately reshown.  This results in a noisy GUI experience.

There should not be a flicker when changing the row selection.

Root Cause

The root cause is as documented in the post.  The sequence of events with RowSelected and RowDeselected means there is a moment while switching rows where no rows are selected.

There is no Syncfusion event that would treat row-switching as a single action, e.g., 1) "RowSelectionChanged", rather than two separate actions, 1) Deselect Old Row, and 2) Select New Row.

For example, this is how Telerik handles the event in their Blazor DataGrid:

<https://docs.telerik.com/blazor-ui/components/grid/selection/rows#selecteditemschanged-event>

Such an event could also be added in Syncfusion, but the current version does not support it.

Use Case

You probably won't see the flicker in your example, even though the event does fire.  We see it in our application because we have two menus, 1) The right-click menu, and 2) An external nav sidebar.  Given the delay involved in updating both menus, we see the GUI "flicker" when switching between rows and right-clicking at the same time.

This is a common user action.  One row is already selected, and the user right-clicks on another row.



PS Prathap Senthil Syncfusion Team August 13, 2024 02:03 PM UTC

Instead of using the RowDeselecetd event, we suggest you handle the customized operation inside the RecordClick handler. Kindly check the attached sample and code snippet for your reference.


Here we have stored the selection record details in a global variable inside RowSelectedEvent and based on the row data we have shown the menu. This will prevent flickering.

Sample: https://blazorplayground.syncfusion.com/embed/hZrTtPiKIXKKDZzh?appbar=true&editor=true&result=true&errorlist=true&theme=bootstrap5

 

<SfGrid ID="GridSizeNew" @ref="Grid" DataSource="@Orders">

 

    <GridSelectionSettings Type="Syncfusion.Blazor.Grids.SelectionType.Multiple" Mode="Syncfusion.Blazor.Grids.SelectionMode.Row"></GridSelectionSettings>

 

 

    <GridEvents TValue="Order"

                RowSelected="RowSelectedHandler"   OnRecordClick="RecordClick"

                RowDeselected="RowDeselectedHandler"

                ></GridEvents>

    <GridColumns>

 

 

        <GridColumn Field=@nameof(Order.OrderID) HeaderText="Order ID" IsPrimaryKey="true" ValidationRules="@(new Syncfusion.Blazor.Grids.ValidationRules{ Required=true})" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Right" Width="120"></GridColumn>

 

        <GridColumn Field=@nameof(Order.CustomerID) HeaderText="Customer Name" ValidationRules="@(new Syncfusion.Blazor.Grids.ValidationRules{ Required=true})" Width="120"></GridColumn>

 

        <GridColumn Field=@nameof(Order.OrderDate) HeaderText=" Order Date" EditType="Syncfusion.Blazor.Grids.EditType.DatePickerEdit" Format="d" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Right" Width="130" Type="Syncfusion.Blazor.Grids.ColumnType.Date"></GridColumn>

 

        <GridColumn Field=@nameof(Order.Freight) HeaderText="Freight" Format="C2" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Right" EditType="Syncfusion.Blazor.Grids.EditType.NumericEdit" Width="120"></GridColumn>

 

        <GridColumn Field=@nameof(Order.ShipCountry) HeaderText="Ship Country" EditType="Syncfusion.Blazor.Grids.EditType.DropDownEdit" Width="150"></GridColumn>

 

    </GridColumns>

 

</SfGrid>

 

 

 

@if (CurrentOrder)

 

{

    <div> Enable menu</div>

}

 

else

 

{

 

    <div>No records selected.</div>

 

}

@code {

 

    SfGrid<Order> Grid;

    public List<Order> Orders { get; set; }

    public bool CurrentOrder { get; set; } = false;

    public Order Columns { get; set; } = new Order();

 

       public bool FirstSelection;

    public async Task RowSelectedHandler(RowSelectEventArgs<Order> args)

    {

        Columns = args.Data;

      

        FirstSelection = true;

      

    }

 

     public void RecordClick(Syncfusion.Blazor.Grids.RecordClickEventArgs<Order> args)

 

    {

            CurrentOrder =true;

        if (Columns.Equals(args.RowData))

        {

         

            if (FirstSelection)

            {

                FirstSelection = false;

               CurrentOrder = false;

            }

            else

            {

                 CurrentOrder =true;

            }

        }

 

    }

 

    public async Task RowDeselectedHandler(RowDeselectEventArgs<Order> args)

    {

      

 

    }

}

 

 


Reference: https://blazor.syncfusion.com/documentation/datagrid/events#onrecordclick



SG Stephen Green August 13, 2024 04:28 PM UTC

Hello, Prathap, thank you for the suggestion.

We are attempting to detect when "deselect all" occurs.  The given solution makes some progress, but doesn't cover all cases.

Using the given solution, "CurrentOrder" can distinguish between A) Switching rows, versus B) Deselecting a row by clicking on it.  That's good so far.

The problem now is, we still cannot distinguish between A) Switching rows, versus C) Deselecting a row by pressing ESC.

Action
CurrentOrder
Should Count as "Deselect"
A) Switching rows
true
no
B) Deselecting a row by clicking on it
false
yes
C) Deselecting a row by pressing ESC
true
yes


You see, there are several ways of deselecting rows, and we need to make sure we are covering all cases when updating our menu options.




PS Prathap Senthil Syncfusion Team August 14, 2024 01:40 PM UTC

We have modified the previously shared sample as per your requirement by resolving the queries mentioned. Kindly check the below attached sample and code snippet  for your reference.


<SfGrid ID="GridSizeNew" @ref="Grid" DataSource="@Orders" @onkeydown="OnKeyDown">

 

    <GridSelectionSettings Type="Syncfusion.Blazor.Grids.SelectionType.Multiple" Mode="Syncfusion.Blazor.Grids.SelectionMode.Row"></GridSelectionSettings>

 

 

    <GridEvents TValue="Order"

                RowSelected="RowSelectedHandler" OnRecordClick="RecordClick"

                RowDeselected="RowDeselectedHandler"></GridEvents>

    <GridColumns>

 

 

        <GridColumn Field=@nameof(Order.OrderID) HeaderText="Order ID" IsPrimaryKey="true" ValidationRules="@(new Syncfusion.Blazor.Grids.ValidationRules{ Required=true})" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Right" Width="120"></GridColumn>

 

        <GridColumn Field=@nameof(Order.CustomerID) HeaderText="Customer Name" ValidationRules="@(new Syncfusion.Blazor.Grids.ValidationRules{ Required=true})" Width="120"></GridColumn>

 

        <GridColumn Field=@nameof(Order.OrderDate) HeaderText=" Order Date" EditType="Syncfusion.Blazor.Grids.EditType.DatePickerEdit" Format="d" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Right" Width="130" Type="Syncfusion.Blazor.Grids.ColumnType.Date"></GridColumn>

 

        <GridColumn Field=@nameof(Order.Freight) HeaderText="Freight" Format="C2" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Right" EditType="Syncfusion.Blazor.Grids.EditType.NumericEdit" Width="120"></GridColumn>

 

        <GridColumn Field=@nameof(Order.ShipCountry) HeaderText="Ship Country" EditType="Syncfusion.Blazor.Grids.EditType.DropDownEdit" Width="150"></GridColumn>

 

    </GridColumns>

 

</SfGrid>

 

 

 

@if (CurrentOrder)

 

{

    <div> Enable menu</div>

}

 

else

 

{

 

    <div>No records selected.</div>

 

}

@code {

 

 

 

 

    public async Task OnKeyDown( Microsoft.AspNetCore.Components.Web.KeyboardEventArgs args)

    {

 

        if (args.Key == "Escape")

 

        {

 

            CurrentOrder = false;

 

        }

 

    }

    public async Task RowSelectedHandler(RowSelectEventArgs<Order> args)

    {

        Columns = args.Data;

        FirstSelection = true;

        CurrentOrder = true;

    }

 

    public void RecordClick(Syncfusion.Blazor.Grids.RecordClickEventArgs<Order> args)

 

    {

        CurrentOrder = true;

        if (Columns.Equals(args.RowData))

        {

 

            if (FirstSelection)

            {

                FirstSelection = false;

                CurrentOrder = false;

            }

            else

            {

                CurrentOrder = true;

            }

        }

 

    }

 

}

 

 


Sample: https://blazorplayground.syncfusion.com/embed/hthJDvWTTqOMXpUN?appbar=true&editor=true&result=true&errorlist=true&theme=bootstrap5



SG Stephen Green August 14, 2024 02:44 PM UTC

Hello, Prathap, this does make more progress.  I hadn't thought to use the standard key-down event since it isn't one of the SfGrid events.  Thank you.

However, we still can't use this solution to detect row deselection.  The "RowDeselected" event picks up the value "true" when pressing ESC.  This is because "RowDeselected" fires before the "onkeydown" event, so it doesn't get a chance to read the newest value of "CurrentOrder".

Here is an updated table for what we're seeing in the latest solution with escape-key handling:

Action
CurrentOrder
(At Time of Deselect)
CurrentOrder
(Postcondition)
Should Count as
"Deselect"
A) Switching rows
true
true
no
B) Deselecting a row by clicking on it
false
false
yes
c) Deselecting a row by pressing ESC
true
false
yes


Postcondition variables are as expected, but we're not seeing the correct value of "CurrentOrder" at time of deselection (the "RowDeselected" event).



SG Stephen Green August 14, 2024 02:47 PM UTC

I'm guessing the "onkeydown" event fires after "RowDeselected" because "RowDeselected" fires down in the body of the grid, whereas the "onkeydown" needs a chance to bubble back up to the parent, so it fires later.  But I don't know for sure.



PS Prathap Senthil Syncfusion Team August 20, 2024 03:03 PM UTC

Based on your query, we previously provided a possible solution to achieve the desired customization without using the RowDeselected event. In our last update, we suggested using the native OnKeyDown event to identify and deselect a record when the Esc key is pressed. Therefore, we recommend using this approach without relying on the RowDeselected event, as explained in the previous solution. Thank you for your understanding.



SG Stephen Green August 20, 2024 03:47 PM UTC

I see.  The reason we need to use "RowDeselected" is because we need to trigger an action to run once all rows are deselected.  But when to trigger the action?

  • Can't trigger in "OnRecordClick" because "RowSelected" might subsequently occur when row-switching.
  • Can't trigger in "RowSelected" because it won't fire when all rows are deselected.

As I understand it, the proposed solution will leave a variable (CurrentOrder) that tells you if all rows are deselected, but it can't trigger an action when that occurs.



SG Stephen Green August 20, 2024 03:57 PM UTC

We're thinking of using the following solution instead.  Given the available options, it may be the most stable despite the use of a timer:

<SfGrid @ref="grid" TValue="RowData">
    <GridSelectionSettings Type="SelectionType.Multiple" Mode="SelectionMode.Row" />
    <GridEvents TValue="RowData" RowDeselected=@OnRowDeselected />
</SfGrid>

@code
{
private SfGrid<RowData>? grid = null;

public Task OnRowDeselected(RowDeselectEventArgs<RowData> args)
{
// Defer, allow yield to row selection, in case of row-switching.
_ = OnRowDeselected();

return Task.CompletedTask;
}

private async Task OnRowDeselected()
{
// Wait to make sure actually deselecting, rather than momentarily switching rows.
await Task.Delay(10);
if ((grid?.SelectedRecords ?? []).Count == 0)
await OnDeselectAll();
}

private Task OnDeselectAll()
{
// TODO
}
}


PS Prathap Senthil Syncfusion Team August 22, 2024 01:07 PM UTC

Thanks for the update,

Regarding your last suggestion, it is not achievable because, for example, when you select the first row and then try to select another row without holding the Ctrl or Shift key, the previous row becomes unselected. At that time, the RowDeselected event will be triggered, and the selected record count will be zero. Therefore, we recommend using the native OnKeyDown event to identify and deselect a record when the Esc key is pressed. Handle the case where no rows are selected and find the selected row using the RecordClick event. Thus, we suggest using this approach rather than relying on the RowDeselected event, as explained in the previous solution. This is the possible way to achieve your requirements. Thank you for your understanding. Please refer to the attached GIF file for your reference. If you are still facing any issues with the previous solution, kindly let us know which scenario you encountered the problem with.


Attachment: GIF_GridSelection_8fee8d35.zip

Loader.
Up arrow icon