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:
- Click row #1 to select.
- Click row #2 to switch selection to row #2.
- 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
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.
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
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.
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
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.
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; } }
}
}
|
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).
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.
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.
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.
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
}
}
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
- 11 Replies
- 3 Participants
-
SG Stephen Green
- Aug 7, 2024 09:15 PM UTC
- Aug 22, 2024 01:07 PM UTC