mui / mui-x

MUI X: Build complex and data-rich applications using a growing list of advanced React components, like the Data Grid, Date and Time Pickers, Charts, and more!
https://mui.com/x/
4.52k stars 1.31k forks source link

[Question] Is is possible to change focused cell in row editing mode when a button is pressed? #8884

Open SusiKette opened 1 year ago

SusiKette commented 1 year ago

Duplicates

Latest version

Summary šŸ’”

Not sure where else to ask this.

I know that this can already be done with tab key, but I was asked to make it so that enter would do that too, and the save the row if on the last cell of the row.

Here is the code I currently run when handling cell key down events:

(params, event) => {
    if(event.code === "Enter") {
        // Get index of current column
        const column = columnConfig.findIndex(o => o.field === params.field);

        // Use that index in for loop to find next visible column
        // length - 1 is to exclude actions column
        for(let i = column; i < columnConfig.length - 1; i += 1) {
            // Don't run this if we are still in the starting column
            if(i !== column) {
                // Check if column is in visibility model
                if(!(columnConfig[i].field in visibilityModel)) {
                    // Not in model -> visible
                    setRowModesModel({ ...rowModesModel, [params.id]: { mode: GridRowModes.Edit, fieldToFocus: columnConfig[i].field } });
                    break;
                }
                else if(visibilityModel[columnConfig[i].field] === true) {
                    // In model and visible
                    setRowModesModel({ ...rowModesModel, [params.id]: { mode: GridRowModes.Edit, fieldToFocus: columnConfig[i].field } });
                    break;
                }
            }
            else {
                // Check if last column before actions column
                // eslint-disable-next-line no-lonely-if
                if(i === columnConfig.length - 2) {
                    setRowModesModel({ ...rowModesModel, [params.id]: { mode: GridRowModes.View } });
                    break;
                }
            }
        }
    }
}

Everything else works fine, but the focused cell doesn't change. Logging the cell the focus should go to gives the correct cell name, but the focus isn't changing.

Examples šŸŒˆ

No response

Motivation šŸ”¦

No response

Order ID šŸ’³ (optional)

No response

yaredtsy commented 1 year ago

hey @SusiKette

To change the focused cell you can use apiRef.current.setCellFocus(rowId,columnFiled).
I think your code can be simplified if you use selectors that come with the packages. for example

   const columnFields = gridVisibleColumnFieldsSelector(apiRef).filter((field) =>
            apiRef.current.isCellEditable(apiRef.current.getCellParams(params.id, field)),
          );

This will give you all visible columns that are editable you do not have to loop to find visible columns. you can refer how its has been implemented for Tab key below.

https://github.com/mui/mui-x/blob/1ee0495437ccc329b0af8b1e8e5cd84a3e0d36b1/packages/grid/x-data-grid/src/hooks/features/editing/useGridRowEditing.ts#L190-L214

m4theushw commented 1 year ago

Could you give more details of what you're trying to implement? I didn't understand. To move the focus to a specific cell you can use apiRef.current.setCellFocus(id, field), but the editing API has some attributes that also allow to control focus. For instance, when changing the mode back to view, you can also configure where the focus goes with cellToFocusAfter.

https://github.com/mui/mui-x/blob/44571c4c2ed6662deb3efa252d282de2bfb14616/packages/grid/x-data-grid/src/models/api/gridEditingApi.ts#L112-L116

SusiKette commented 1 year ago

I'm trying to use apiRef, but I get a Cannot read properties of undefined (reading 'current') whenever I try to use apiRef. I think I had this same issue before, which is probably why I started avoiding using `apiRef.

Currently I'm setting the apiRef like this const apiRef = useGridApiRef();.

I also tried const apiRef = useGridApiContext();, but that gives a Could not find the data grid context. It looks like you rendered your component outside of a DataGrid, DataGridPro or DataGridPremium parent component. error.

yaredtsy commented 1 year ago

have you assigned the apiRef to the grid?

const apiRef = useGridApiRef();
return <DataGrid ref={apiRef} />