Modifier Key State Detection during SfGrid's OnRecordClick event

I seek a reliable technique for detecting the `pressed` versus `not-pressed` state of the `Control`, `Shift`, and `Alternate` modifier keys within the `SfGrid`s `OnRecordClick` event handler. I have tried a few different techniques so far without success. This is proving a trickier than I would have suspected. As one example, whereas many if not most keys' pressed state can be detected successfully using Robert Hurst's `Keystrokes.js` library, these three particular modifier keys are not detected correctly within the `OnRecordClick` handler. Since `SfGrid` does not expose key[down|up|press] events directly, one must use JS interop manually. Refer to SyncfusionBlazorGridEvents playground app which exposes all 92 grid events.

My use case is simple. When a record is clicked on, I want to trigger different response logic depending on the pressed versus not-pressed state of the `Control`, `Shift`, and `Alternate` modifier keys.


3 Replies

MS Monisha Saravanan Syncfusion Team January 11, 2024 01:33 PM UTC


Hi Calvin,


Greetings from Syncfusion.


We suspect that you are expecting to find the keys pressed at your end while performing record click. If so we would like to inform that while clicking the record, RowSelect event will be triggered and we can find  IsCtrlPressed or IsShiftPressed or IsInteracted from the event args of RowSelecting event.


Reference: https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.RowSelectingEventArgs-1.html#properties


Or alternatively we can find the key pressed using a javascript solution. If you are satisfied with javascript solution then kindly get back to us and based on your confirmation we will prepare sample as per your requirement.


Regards,

Monisha



CA Calvin January 12, 2024 01:45 PM UTC

Thanks Monisha! I had tried that approach previously. But rather than targeting the `RowSelecting` event, I instead targeted the `CellSelecting` event since that event's arguments also include the targeted cell's column index. And from the cell's column index, one can ascertain the corresponding field name which is needed for filtering.


Unfortunately, the `CellSelecting` event does not correctly report the `CurrentValue` of the targeted cell when one or more columns are grouped. Presumably, ***this is a bug***. It does, however, provide the correct `CurrentValue` of the targeted cell when column/field grouping is not applied. But one can work around this issue by reflecting over the `Data` property to obtain the current value of the targeted cell.


Unfortunately, responding in the `CellSelecting` handler is not as robust as responding in the `OnRecordClick` handler. This is because one must click on a second time on the cell if the cell is already selected in order to trigger the event. So this experience is not as intuitive for the user.


For reference, here is a simple implementation comparison:



```cs

public async Task CellSelectingHandlerAsync(CellSelectingEventArgs<Item> args) {

    if (args.IsCtrlPressed) {

        List<string> columnFieldNamesList = await _grid.GetColumnFieldNamesAsync();

        string targetColumnName = columnFieldNamesList[args.CellIndex]; // <-- TODO: Is this generally robust (i.e., if columns are hidden or moved for example)?

        object? cellValue = args.Data.GetType().GetProperty(name: targetColumnName)?.GetValue(obj: args.Data, index: null);

        // Can't use instead `cellValue = args.CurrentValue` here because `args.CurrentValue` is not set correctly when column/field grouping is applied to grid

        if (cellValue is null) { return; }

        List<object> currentFilterValues = _grid.FilterSettings.Columns.Where(_ => _.Field == targetColumnName).Select(_ => _.Value).ToList();

        List<object> filterValues = new List<object> { cellValue }.Concat(currentFilterValues).Distinct().ToList();

        if (args.IsShiftPressed) {

            await _grid.FilterByColumnAsync(targetColumnName, filterOperator: FilterOperator.NotEqual.ToOperatorName(), filterValue: filterValues, predicate: "and");

        } else {

            await _grid.FilterByColumnAsync(targetColumnName, filterOperator: FilterOperator.Equal.ToOperatorName(), filterValue: filterValues, predicate: "or");

        }

    }

}


public async Task OnRecordClickHandlerAsync(RecordClickEventArgs<Item> args) {

    string columnName = args.Column.Field;

    object? cellValue = args.RowData.GetType().GetProperty(name: columnName)?.GetValue(obj: args.RowData, index: null);

    if (cellValue is null) { return; }

    List<object> currentFilterValues = _grid.FilterSettings.Columns.Where(_ => _.Field == columnName).Select(_ => _.Value).ToList();

    List<object> filterValues = new List<object> { cellValue }.Concat(currentFilterValues).Distinct().ToList();

    //Implementation uses https://github.com/RobertWHurst/Keystrokes?tab=readme-ov-file

    if (await KeyState.IsDownKeyFAsync()) { // Would prefer to use the CTRL key (but need technique to reliably discover its pressed state)

        if (await KeyState.IsDownKeyDAsync()) { // Would prefer to use ALT key

            await _grid.FilterByColumnAsync(columnName, filterOperator: FilterOperator.NotEqual.ToOperatorName(), filterValue: filterValues, predicate: "and");

        } else {

            await _grid.FilterByColumnAsync(columnName, filterOperator: FilterOperator.Equal.ToOperatorName(), filterValue: filterValues, predicate: "or");

        }

    }

}

```



PS Prathap Senthil Syncfusion Team January 15, 2024 05:21 AM UTC

Before proceeding with the reporting problem, we require some additional clarification from your end. Please share the below details to proceed further at our end.

  • Share with us a grid code snippet with the model class.
  • Share with us the NuGet version you have used.
  • Could you please share an issue-reproducible sample.

Above-requested details will be very helpful in validating the reported query at our end and providing a solution as early as possible.


Loader.
Up arrow icon