syncfusion / flutter-widgets

Syncfusion Flutter widgets libraries include high quality UI widgets and file-format packages to help you create rich, high-quality applications for iOS, Android, and web from a single code base.
1.6k stars 783 forks source link

Flutter on TabKey Focus not Moving Properly #2153

Open abdulrehmananwar opened 3 weeks ago

abdulrehmananwar commented 3 weeks ago

Bug description

i have write a logic on buildEditWidget event after that focus travel on tab key not working properly . my code is as below. if (column.columnName == 'Quantity2') { return null; }

Steps to reproduce

@override Widget? buildEditWidget(DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, GridColumn column, CellSubmit submitCell) { // Check if the column is 'Quantity2' and return null if so if (column.columnName == 'Quantity2') { return null; }

// Fetch the current cell value to display
final String displayText = dataGridRow
    .getCells()
    .firstWhereOrNull(
        (DataGridCell dataGridCell) => dataGridCell.columnName == column.columnName)
    ?.value
    ?.toString() ??
    '';
newCellValue = _isPasting.value ? null : displayText;

// Create a TextEditingController to manage text input
final TextEditingController editingController = TextEditingController(
  text: displayText,
);

return Focus(
  onKeyEvent: (node, keyEvent) {
    if (keyEvent.logicalKey == LogicalKeyboardKey.keyV &&
        HardwareKeyboard.instance.isControlPressed) {
      handlePasteAndNavigate(rowColumnIndex.rowIndex, rowColumnIndex.columnIndex);
      return KeyEventResult.handled;
    }
    return KeyEventResult.ignored;
  },
  child: TextField(
    autofocus: true,
    controller: editingController,
    decoration: const InputDecoration(
      contentPadding: EdgeInsets.fromLTRB(0, 0, 0, 8.0),
    ),
    onChanged: (String value) {
      if (value.isNotEmpty) {
        newCellValue = value;
      }
    },
    onSubmitted: (String value) {
      // Submit the cell's value
      submitCell();
    },
  ),
);

}

Code sample

import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:flutter/services.dart'; import 'package:collection/collection.dart';

class CustomSelectionManager extends RowSelectionManager { CustomSelectionManager({ required this.isDialogOpen, required this.dataGridController, required this.dataGridSource, required this.context, required this.lastColumnIndex, });

final bool isDialogOpen; final DataGridController dataGridController; final DataGridSource dataGridSource; final int lastColumnIndex; final BuildContext context;

@override Future handleKeyEvent(KeyEvent keyEvent) async { if (keyEvent.logicalKey == LogicalKeyboardKey.tab || keyEvent.logicalKey == LogicalKeyboardKey.enter) { if (!isDialogOpen) { await super.handleKeyEvent(keyEvent).then( (value) => WidgetsBinding.instance.addPostFrameCallback((_) async { await dataGridController .beginEdit(dataGridController.currentCell); }), ); } } } }

class GridEntryDataSource extends DataGridSource { GridEntryDataSource(this.dataGridController, this.fieldNames) { _initializeDataList(); updateDataGridRows(); }

DataGridController dataGridController; final List fieldNames; List dataGridRows = []; List<Map<String, String>> dataList = []; // Change _isPasting to ValueNotifier final ValueNotifier _isPasting = ValueNotifier(false);

dynamic newCellValue;

void _initializeDataList() { dataList.add({for (var v in fieldNames) v: ''}); }

@override List get rows => dataGridRows;

void updateDataGridRows() { dataGridRows = dataList.map((data) => _createDataRow(data)).toList(); notifyListeners(); }

DataGridRow _createDataRow(Map<String, String> data) { return DataGridRow( cells: fieldNames .map((field) => DataGridCell(columnName: field, value: data[field])) .toList(), ); }

Future handlePasteAndNavigate( int startRowIndex, int startColumnIndex) async { if (_isPasting.value) return; _isPasting.value = true; final clipboardData = await Clipboard.getData('text/plain');

if (clipboardData != null) {
  List<String> rows = clipboardData.text!.split('\n');

  for (int i = 0; i < rows.length - 1; i++) {
    List<String> columns = rows[i].split('\t');

    // Ensure we have enough rows in the dataList.
    while (dataList.length <= startRowIndex + i) {
      dataList.add({for (var v in fieldNames) v: ''});
    }

    for (int j = 0; j < columns.length; j++) {
      if (startColumnIndex + j < fieldNames.length) {
        newCellValue = null;
        int rowIndex = startRowIndex + i;
        int colIndex = startColumnIndex + j;

        // Enter edit mode for the target cell
        RowColumnIndex rowColumnIndex = RowColumnIndex(rowIndex, colIndex);
        // Add a minimal delay before entering edit mode
        await Future.delayed(const Duration(milliseconds: 100));
        await dataGridController.beginEdit(rowColumnIndex);

        // Ensure that cell submission is processed after a slight delay
        await Future.delayed(const Duration(milliseconds: 100));
        _onCellSubmitted(
            dataGridRows[rowIndex], fieldNames[colIndex], columns[j]);

        // Move to the edited cell and end edit mode
        dataGridController.moveCurrentCellTo(rowColumnIndex);
        dataGridController.endEdit();
      }
    }
  }
}
_isPasting.value = false;

}

void resetGrid() { dataList.clear(); _initializeDataList(); updateDataGridRows(); }

Future _onCellSubmitted( DataGridRow row, String columnName, String value) async { final rowIndex = dataGridController.currentCell.rowIndex;

// Validate and assign value to the correct dataList entry.
if (rowIndex >= 0 && rowIndex < dataList.length) {
  dataList[rowIndex][columnName] = value;

  // Add a new row if the last row is filled.
  if (rowIndex == dataList.length - 1 &&
      dataList[rowIndex].values.any((v) => v.isNotEmpty)) {
    dataList.add({for (var v in fieldNames) v: ''});
    if (dataGridController.currentCell.columnIndex == 0) {
      final lastData = dataList.last;
      dataGridRows.add(_createDataRow(lastData));
      notifyListeners();
    }
  }
} else {
  print("Invalid row index during submission: $rowIndex");
}

}

@override Future onCellSubmit(DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, GridColumn column) async { // Get the current row index from the data grid controller. final currentRowIndex = dataGridController.currentCell.rowIndex;

// Check if the current row index is valid.
if (currentRowIndex < 0 || currentRowIndex >= dataList.length) {
  print("Invalid row index: $currentRowIndex");
  return;
}

// Retrieve the field name based on the current column index.
var names = fieldNames[dataGridController.currentCell.columnIndex];

dynamic value = dataList[currentRowIndex][names];

if (value == newCellValue) {
  return;
}

// Update the value if the new cell value is not null or empty.
if (newCellValue != null &&
    newCellValue.isNotEmpty &&
    value != newCellValue) {
  value = newCellValue;
  dataList[currentRowIndex][names] = value;
}

// If the updated value is valid, update the corresponding cell in the data grid row.
if (value != null && value.isNotEmpty) {
  if (column.columnName == names) {
    dataGridRows[currentRowIndex]
        .getCells()[dataGridController.currentCell.columnIndex] =
        DataGridCell<String>(columnName: names, value: value);
  }
}

}

@override Future canSubmitCell(DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, GridColumn column) async { return Future.value(true); }

@override DataGridRowAdapter buildRow(DataGridRow row) { return DataGridRowAdapter( cells: row.getCells().map((cell) { return Container( alignment: Alignment.center, child: Text(cell.value?.toString() ?? ''), ); }).toList(), ); }

@override Widget? buildEditWidget(DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, GridColumn column, CellSubmit submitCell) { // Check if the column is 'Quantity2' and return null if so if (column.columnName == 'Quantity2') { return null; }

// Fetch the current cell value to display
final String displayText = dataGridRow
    .getCells()
    .firstWhereOrNull(
        (DataGridCell dataGridCell) => dataGridCell.columnName == column.columnName)
    ?.value
    ?.toString() ??
    '';
newCellValue = _isPasting.value ? null : displayText;

// Create a TextEditingController to manage text input
final TextEditingController editingController = TextEditingController(
  text: displayText,
);

return Focus(
  onKeyEvent: (node, keyEvent) {
    if (keyEvent.logicalKey == LogicalKeyboardKey.keyV &&
        HardwareKeyboard.instance.isControlPressed) {
      handlePasteAndNavigate(rowColumnIndex.rowIndex, rowColumnIndex.columnIndex);
      return KeyEventResult.handled;
    }
    return KeyEventResult.ignored;
  },
  child: TextField(
    autofocus: true,
    controller: editingController,
    decoration: const InputDecoration(
      contentPadding: EdgeInsets.fromLTRB(0, 0, 0, 8.0),
    ),
    onChanged: (String value) {
      if (value.isNotEmpty) {
        newCellValue = value;
      }
    },
    onSubmitted: (String value) {
      // Submit the cell's value
      submitCell();
    },
  ),
);

}

}

class DataGridExample extends StatefulWidget { const DataGridExample({super.key});

@override // ignore: library_private_types_in_public_api _DataGridExampleState createState() => _DataGridExampleState(); }

class _DataGridExampleState extends State { List fieldNames = ['ItemName', 'Quantity', 'Quantity2', 'Price', 'Amount']; late DataGridController dataGridController; late GridEntryDataSource dataSource;

String selectedOption = 'AgeFields';

@override void initState() { super.initState(); dataGridController = DataGridController(); dataSource = GridEntryDataSource(dataGridController, fieldNames); }

void changeColumns(String option) { setState(() { selectedOption = option; fieldNames.clear(); dataGridController = DataGridController(); dataSource = GridEntryDataSource(dataGridController, fieldNames); }); }

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Editable DataGrid Example'), actions: [ ValueListenableBuilder( valueListenable: dataSource._isPasting, builder: (context, isPasting, child) { return IgnorePointer( ignoring: isPasting, child: IconButton( icon: const Icon(Icons.paste), onPressed: () async { final focusedCell = dataSource.rows.first; int rowIndex = dataSource.rows.indexOf(focusedCell); await dataSource.handlePasteAndNavigate(rowIndex, 0); }, ), ); }, ), ValueListenableBuilder( valueListenable: dataSource.isPasting, builder: (context, isPasting, child) { return IgnorePointer( ignoring: isPasting, child: IconButton( icon: const Icon(Icons.refresh), onPressed: () { dataGridController.endEdit(); WidgetsBinding.instance.addPostFrameCallback(() { dataSource.resetGrid(); }); }, ), ); }, ), ], ), body: Column( children: [ Expanded( child: SfDataGrid( allowColumnsResizing: true, selectionMode: SelectionMode.single, navigationMode: GridNavigationMode.cell, editingGestureType: EditingGestureType.tap, allowEditing: true, source: dataSource, controller: dataGridController, selectionManager: CustomSelectionManager( isDialogOpen: false, dataGridController: dataGridController, dataGridSource: dataSource, context: context, lastColumnIndex: fieldNames.length - 1, ), columns: fieldNames.map((fieldName) { return GridColumn( columnName: fieldName, label: Container( alignment: Alignment.center, child: Text(fieldName, style: const TextStyle(fontWeight: FontWeight.bold)), ), ); }).toList(), ), ), ], ), ); } }

void main() { runApp(const MaterialApp( home: DataGridExample(), debugShowCheckedModeBanner: false, )); }

Screenshots or Video

Screenshots / Video demonstration [Upload media here]

Stack Traces

Stack Traces ```dart [Add the Stack Traces here] ```

On which target platforms have you observed this bug?

Windows

Flutter Doctor output

Doctor summary (to see all details, run flutter doctor -v): [√] Flutter (Channel stable, 3.24.4, on Microsoft Windows [Version 10.0.19045.5073], locale en-US) [√] Windows Version (Installed version of Windows is version 10 or higher) [√] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [√] Chrome - develop for the web [√] Visual Studio - develop Windows apps (Visual Studio Professional 2022 17.10.4) [√] Android Studio (version 2024.2) [√] Connected device (3 available) [√] Network resources

abineshPalanisamy commented 3 weeks ago

Hi @abdulrehmananwar ,

Based on the details provided, in the buildEditWidget, you have returned null for the Quantity2 column. The buildEditWidget is used to obtain the TextField widget when a cell is moved into edit mode. Therefore, while the cell was intended to be moved into edit mode, you have restricted the addition of the TextField widget by returning null. As a result, the cells in the Quantity2 column did not enter edit mode, even though focus switched to it. We believe that the cells in the Quantity2 column not entering edit mode is the issue you encountered.

To better assist you with your query, could you clarify why you are restricting the addition of the TextField widget for the cells in the Quantity2 column when focus switches?. Additionally, please provide a video recording demonstrating the issue for better clarity. Please provide relevant details that may help us better understand your request.

Regards, Abinesh P

abdulrehmananwar commented 3 weeks ago

I am currently facing three major issues with focus management when handling the CanCellSubmit event, particularly when opening a dialog to filter search results based on user input.

TextField Not Focusable: When the dialog opens, the TextField within it is not receiving focus. Even when clicked, it does not gain focus, which prevents the user from entering input.

Dialog Reopening Upon Dismissal: If the dialog is dismissed without selecting any value, it unexpectedly reopens immediately. On the second dismissal, it closes properly. The dialog should only reopen if the user presses the Tab key or clicks elsewhere, not automatically upon dismissal.

Focus Management in Price Column: I have a price column where user input is not required, so I do not return a TextField in the widget builder. However, this causes issues with focus traversal when using the Tab key, as the focus does not move as expected.

i have shared you sample Code and video please respond on it Thanks.

https://github.com/user-attachments/assets/0f5c454f-480d-4a2c-a059-c5451f4b018f GridIssues.zip

abineshPalanisamy commented 2 weeks ago

Hi @abdulrehmananwar

 

Query Response
Dialog Reopening Upon Dismissal: If the dialog is dismissed without selecting any value, it unexpectedly reopens immediately. On the second dismissal, it closes properly. The dialog should only reopen if the user presses the Tab key or clicks elsewhere, not automatically upon dismissal. I have adjusted the sample you provided, and we have resolved the issue with opening and closing the dialog box. In the handleKeyEvent method of the RowSelectionManager, we need to set the dialog box flag variable to true after handling the key event and then to false when appropriate. This will rectify the issue with the dialog box opening and closing.
Focus Management in Price Column: I have a price column where user input is not required, so I do not return a TextField in the widget builder. However, this causes issues with focus traversal when using the Tab key, as the focus does not move as expected. After rectifying the issue, the dialog box now opens and closes properly. We are unable to reproduce the focus traversal issue when using the Tab key on our side. Based on the video reference, we attempted to replicate the issue, but it seems to have been resolved.
TextField Not Focusable: When the dialog opens, the TextField within it is not receiving focus. Even when clicked, it does not gain focus, which prevents the user from entering input. Based on the details provided, you are triggering the showDialog in the canSubmitCell method. The DataGridSource.canSubmitCell is called before the cell finishes editing. If you want to prevent the cell from ending its editing state, you can return false. In this scenario, the DataGrid cell remains in edit mode with the TextField active, so the focus is maintained solely on the DataGrid. When the dialog box opens, the focus stays on the DataGrid because the cell is still in edit mode.   Instead of triggering the dialog box in canSubmitCell, you can directly invoke showDialog in the buildEditWidget method for the specific cell based on the columnName, rather than loading the TextField widget.  

If there are any misunderstandings regarding your requirements, or if your needs differ, please provide specific and clear details about why you are using showDialog in canSubmitCell. What is the core reason for including the dialog? This additional information will help us thoroughly address your request and provide an appropriate solution.


We have included a modified sample for your reference. Please review it for further details

 </o:p>

Regards,

Abinesh P

abdulrehmananwar commented 2 weeks ago

Point Number 3 is still pending. You suggested invoking showDialog in the buildEditWidget method for the specific cell based on the columnName, instead of directly loading the TextField widget.

However, the TextField widget is necessary due to the following requirements:

Unfocus Behavior: When the TextField loses focus, we need to validate the input: If the input is not empty and differs from the original value: First, check if the input matches an item in the dialog's list: If the match count is 1, accept the input without opening the dialog. If the match count is greater than 1, open the dialog for the user to filter further. Second, if the user closes the dialog without selecting an item, submission will remain disabled until a valid value is selected or the input is cleared.

https://github.com/user-attachments/assets/51e10a87-603a-43e3-be2b-5006308f6e9e

abdulrehmananwar commented 2 weeks ago

Issue Number 2 still not resolved. on buildEditWidget simply return null for all cells. and press tab key it not moving. properly.

abineshPalanisamy commented 2 weeks ago

Hi @abdulrehmananwar ,

TextField Not Focusable:

We have modified the sample according to your requirements. Instead of placing the DialogBox in the canSubmitCell method, we have now added it in the handleKeyEvent method. Additionally, we called DataGridController.endEdit to remove the focus from the TextField and allow focus to be set on the TextField within the dialog box. We have included a sample for your reference. Please review it for further details.

Press tab key it not moving Properly:

We have checked on our end, and the Tab key is working properly in the DataGrid. Tab key behavior moves the focus from the current cell to the next active cell. In your case, for the price column, you have a buildEditWidget that simply returns null for all cells, so the cell does not move into edit mode. When you press Tab, the focus switches to the price cell, but the cell doesn't enter edit mode.

We currently do not have direct support for copying and pasting cell content in the DataGrid. You have achieved this behavior through a custom implementation in the sample, but this approach may cause various issues in several use cases.

At present, the DataGrid does not support copying and pasting cell content. However, we have already considered your request as a feature for future releases. During the planning phase of each release cycle, we review all open feature requests and prioritize them based on factors such as product vision, technological feasibility, and customer demand. We appreciate your patience and understanding as we work towards implementing this feature. You can follow up with the feedback link provided for further updates.

Feedback link: 37701

Regards, Abinesh P

abdulrehmananwar commented 2 weeks ago

1-You can remove Copypaste Feature from this code its not required. 2-Currently, the dialog only opens when the Tab key is pressed. However, I need it to open when the TextField loses focus, provided that the TextField has a value and is not empty 2-The dialog should open only when the user enters a value into the TextField. 3-If the user closes the dialog without making a selection, the cell should automatically re-enter edit mode. 4-On losing focus, the dialog should reopen until the user either selects a value or clears the TextField. 5-Currently Dialog Opening only on TabKey butt i need this to open on textfield Unfocus if TextField value input and not empty 6- Focus issue persists when the widget is null. I’m not referring to edit mode—just aiming for smooth focus movement, which isn’t happening as expected. Please refer to the attached video for clarification.

https://github.com/user-attachments/assets/3c07ccd8-2345-4d1e-a85b-de802c0b9ca3

abineshPalanisamy commented 2 weeks ago

Hi @abdulrehmananwar

Based on the requirements, we have modified the sample to meet your needs. To open the dialog box when the TextField loses focus, we added the dialog box in the onFocusChange callback of the Focus widget. Additionally, we have addressed other focus management issues. Please refer to the sample for more details, and we have attached a video reference as well.

Video reference :

https://github.com/user-attachments/assets/c4b0d099-affd-4c02-9b3f-92f6768cba72

Regards, Abinesh P

abdulrehmananwar commented 2 weeks ago

There are still several issues persisting:

1-When I press the Tab key without any input in the search text field, it doesn’t move to the next cell as expected. 2-The search dialog only opens for the first row but should open for each row. 3-When the search dialog opens, it currently clears the text in the background text field. However, this text should remain if the user cancels the dialog. Additionally, focus should stay on the cell until the user either selects a valid value from the dialog or clears the text field. 4-As shown in the video, sometimes when I clear the search text field and press the Tab key, the dialog still opens, and the Tab key does not behave as expected. 5- As demonstrated, when I click on the Quantity column, input a quantity, the value becomes invisible.

https://github.com/user-attachments/assets/c2e6a392-38a3-4d06-9b94-56a9a4fbb9ca

abineshPalanisamy commented 1 week ago

Hi @abdulrehmananwar

We have addressed some of the issues and use cases in the sample. We have ensured that the specific use cases you mentioned are included, and we’ve provided a sample and video for your reference.

If you encounter any other issues, please review the entire sample and provide all related use cases. This will help us verify all expected behaviors and ensure that any remaining issues are resolved.

Video :

https://github.com/user-attachments/assets/6209d43e-e56a-4aff-8805-96407739331a

Regards, Abinesh P

abdulrehmananwar commented 1 week ago

1-Tab Key Navigation: Pressing Tab in the Price column causes a slight lag, making the transition feel unsmooth. Additionally, Shift+Tab does not function properly in the Price column. 2- I need an additional functionality where, when the user unfocuses or presses the Tab key, the system checks if the entered value (e.g., '1') exists in the filter list. If the value occurs exactly once in the list, it should be automatically selected in the grid without opening the dialog box. If the value is not found or appears more than once, the dialog box should open for manual selection Remember, Step 2 should always involve checking data asynchronously with await. For example, it will call an API to fetch a list and filter the data. The await functionality works fine when the user presses the Tab key, but it doesn't work correctly when the user unfocuses the cell by clicking with the mouse

abdulrehmananwar commented 1 week ago

Issue 1 was resolved by defining the CustomSelectionManager in initState and passing it to the build widget, rather than defining it directly within the build widget. butt i dont want to create into initState cause i am rebuilding Gridview. so i cannot define it on initState .

abineshPalanisamy commented 1 week ago

Hi @abdulrehmananwar ,

As per your requirements, we have modified the sample. Now, the dialog box will open when the entered value does not match any items in the list. In showSelectionDialog, we added logic to check for value matches. In the provided sample, we are currently using a local list to achieve this behavior. To assist you further, could you please provide more details about your requirements, specifically regarding fetching the list of records from an API and applying filtering?

Regarding the Shift+Tab issue: all cells except for the ItemName column handle Shift key navigation and the Tab key properly. For the ItemName column, when the dialog box opens, it waits for a value to be chosen. However, this wait causes the framework to recognize the Shift key as inactive, preventing the DataGrid from detecting the Shift key press and thus disrupting navigation for this specific column. Unfortunately, this is a limitation on the DataGrid side that we cannot directly handle.

If you encounter any additional issues, please review the entire sample and provide all use cases. We will test each use case to confirm that expected behaviors function properly without impacting existing features, and we’ll address any remaining issues to ensure they are fully resolved.

SfDataGrid.zip

Video:

https://github.com/user-attachments/assets/13570b0d-1369-4a1f-a3ad-204624de1c78

Regards, Abinesh P

abdulrehmananwar commented 1 week ago

Issue 1: Initially, the CustomSelectionManager was moved to initState and passed to the build widget instead of being defined directly within the build widget. However, I would prefer not to define it in initState because I am rebuilding the GridView, so placing it in initState does not meet the requirements.

Issue 2: As mentioned, the list view data comes from the API on each unfocus event. Currently, you have hardcoded this list as List searchRecord = ["1", "2", "3"];, which is fine for now. Also, please call await Future.delayed(Duration(seconds: 10)); before returning the list. This setup works as expected when pressing the Tab key, but if a user enters input and then clicks on another cell, it doesn't trigger as expected."

abineshPalanisamy commented 1 week ago

Hi @abdulrehmananwar ,

Issue 1: We are unable to replicate the reported issue on our end. To assist you better, could you kindly provide more details regarding your requirements? Additionally, please share a video recording demonstrating the issue for better clarity.

Issue 2: We are unable to achieve the desired behavior on our end. When switching the focus of the cell via a mouse click and waiting for the list, the onTap event of the cell, wrapped in a GestureDetector, gets triggered by the framework at the source level. The framework's onTap event doesn't account for the delay we have introduced, which causes the issue and prevents the required behavior from being achieved.

Regards, Abinesh P

abdulrehmananwar commented 1 week ago

please provide any solution of Issue 2. Make something on can submit to resolve issue 2.

SethupathyD commented 6 days ago

Hi @abdulrehmananwar

We have resolved your query by introducing a bool property. With this property, we have restricted the begin edit to commit with a delay. We have shared the main.dart file for your reference. Kindly test it on your end to ensure it fits with all other scenarios in your use case.

Regards, Sethupathy D.

abdulrehmananwar commented 6 days ago

Issue 1: When pressing the Tab key, navigation is not smooth on the Price column because the widget for the Price column contains a null widget on buildEditWidget. Additionally, using Shift + Tab to move the focus backward does not work correctly. Upon analysis, I found that defining a CustomSelectionManager in initState resolves the issue. However, I prefer not to define it during initialization because the GridView needs to be dynamically built from the parent.

Issue 2: When I press the Tab key multiple times, it opens multiple search Dialogs.

Please Resolve both Issue . Thanks i have attached sample videos

https://github.com/user-attachments/assets/66afef1c-7f32-4523-af0e-5db6d0207e36

https://github.com/user-attachments/assets/8ad826c9-3ce9-4865-8f92-56e537d95d7f

SethupathyD commented 4 days ago

Hi @abdulrehmananwar 

Issue 1 : When Pressing the Tab key Navigation is not smooth on Prize column.

We reviewed your query but were unable to replicate the issue on our end. Navigation on the prize column was smooth. We have shared a video demo for your reference.

https://github.com/user-attachments/assets/c55f969c-f82a-476d-b6f2-8f64f6278895

Shift + Tab to move the Focus is improper.

We encountered this issue when the focus was on the first row in the first column. We have addressed the issue. Kindly get back to us after testing it on your end.

Issue 2 : When I press the Tab key multiple times, it opens multiple search Dialogs.

We have addressed this issue in the attached zip file. Kindly test it on your end to ensure it works with all other scenarios in your use case.

Sample Zip: SfDataGrid.zip

Regards, Sethupathy D.

abdulrehmananwar commented 3 days ago

1- Issue 1: Occurs during hot restart of the application. 2- When there are enough rows in the grid to enable a scrollbar, and at the beginning of the grid, performing a Ctrl+V followed by the Enter key sometimes causes the focus to jump to the last cell of the grid unexpectedly

Video on Issue 1. https://github.com/user-attachments/assets/bea3cde3-5129-4e61-aa26-5af6401185bd

Video on Issue 2.

https://github.com/user-attachments/assets/c8e6af9b-7d04-4276-97d7-6b940687000b

abineshPalanisamy commented 55 minutes ago

Hi @abdulrehmananwar,

Issue 1: Occurs during hot restart of the application.

As per the video reference, we have checked your case on our side. After reloading and restarting, the Tab key navigation functions properly on our end. Cell editing also works correctly with both the Tab key and Shift+Tab key. We have included the video reference for your review.

https://github.com/user-attachments/assets/12381eb8-dfcc-4027-a803-05b6326a8972

Issue 2 : performing a Ctrl+V followed by the Enter key sometimes causes the focus to jump to the last cell of the grid unexpectedly.

You can restrict the mentioned action in the handleKeyEvent method of the RowSelectionManager. We have included a sample with the resolved state. Kindly review it.

Additionally, please note that you can implement or restrict your custom actions in the handleKeyEvent() override of the custom selection manager class, which is derived from RowSelectionManager.

Regards, Abinesh P