Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Customizing Functionality and Appearance of Editable DataGrid Cell #8854

Closed
2 tasks done
conerye opened this issue May 3, 2023 · 4 comments
Closed
2 tasks done

Customizing Functionality and Appearance of Editable DataGrid Cell #8854

conerye opened this issue May 3, 2023 · 4 comments
Labels
component: data grid This is the name of the generic UI component, not the React module! support: commercial Support request from paid users

Comments

@conerye
Copy link

conerye commented May 3, 2023

Order ID or Support key 💳 (optional)

331993142

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

The problem in depth 🔍

I have a table defined with an editable column of type number.

This is a TWO PART QUESTION:

  1. I would like to define min and max values for the number and have it display in error (red) if values are entered outside of the range, so that it would work similar to a text field input (the way TextField uses inputProps and error props). I found the following online: https://stackoverflow.com/questions/74513146/define-min-and-max-input-values-on-mui-datagrid-number-column-cell and added it to my column definition, and the range checking is working... but adding an error prop did not work and I was unable to find any API documentation for GridEditInputCell. I posted question [question] How to Customize Functionality and Appearance of Editable DataGrid Cell? #8769 and was told to use preProcessEditCellProps. I have added the use of preProcessEditCellProps for the validation and error prop as follows:
    preProcessEditCellProps: (params) => {
    const hasError = params.props.value < 0 || params.props.value > params.row.licensesAvailable;
    const inputProps = { max: params.row.licensesAvailable, min: 0 };
    return { ...params.props, error: hasError, inputProps };
    }
    However, this did not resolve the issue because setting error true does not render the input in red (range restriction still works this way tho). Also, it just seems to stay 'stuck' in edit mode and the value remains unchanged.

  2. I would like to change the appearance of the editable column to make the editable cells obvious to the user without them having to double-click to see the input. is that possible? and if yes, how?

PLEASE DO NOT CLOSE until there have been responses to both parts of the question.

Your environment 🌎

`npx @mui/envinfo`
  Don't forget to mention which browser you used.
  Output from `npx @mui/envinfo` goes here.
@conerye conerye added status: waiting for maintainer These issues haven't been looked at yet by a maintainer support: commercial Support request from paid users labels May 3, 2023
@zannager zannager added the component: data grid This is the name of the generic UI component, not the React module! label May 4, 2023
@m4theushw m4theushw removed the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label May 4, 2023
@m4theushw
Copy link
Member

  1. Besides adding preProcessEditCellProps, you also need to provide a custom edit component to react to the error prop. Returning error: true only signals to the DataGrid that the input contains an error and it shouldn't be saved, presenting the error is a job for the edit component. The demo in https://mui.com/x/react-data-grid/editing/#validation containas a full example.
  2. Not sure if I understood. The cells that are editable have the MuiDataGrid-cell--editable CSS class. You can customize the style targeting this class. Doing that, you still need to double-click the cell to enter the edit mode. If you're looking for something like entering the edit mode with a single click, then look at the demo in [docs] Add recipe for single-click editing #8365

@conerye
Copy link
Author

conerye commented May 4, 2023

OK, let me see if I can better explain what I mean on part 2. A modal opens with table that has only the last column editable, here is a snip:
image
However, it is not obvious that the last column is editable! Would be great if the cells in the last column column could look like this, with the outlined input showing:
image
The input value up/down arrows show only when hovering over the input (which is fine):
image

Regarding the response above, I have added a custom edit component for the editable column but not sure I am doing it correctly. I have also added the props to the table for single-click editing. Here is what I have:

// editable column for export table
{
    field: 'exportCount',
    align: 'left',
    editable: true,
    flex: 1,
    headerAlign: 'left',
    headerName: 'Export',
    preProcessEditCellProps: (params) => {
        const hasError =
            params.props.value < 0 || params.props.value > params.row.licensesAvailable;
        return { ...params.props, error: hasError };
    },
    renderEditCell: (params) => {
        const inputProps = { max: params.row.licensesAvailable, min: 0 };
        return <TextFieldEditInputCell {...params} inputProps={inputProps} type="number" />;
    },
    type: 'number',
}

// the custom input component
const TextFieldEditInputCell = (cellData) => {
const { id, error, field, inputProps, value } = cellData;
const ref = useGridApiContext();

const handleChange = async (event) => {
    const newValue = event.target.value; // The new value entered by the user
    ref.current.setEditCellValue({ id, field, value: newValue });
};

return (
    <TextField
        error={error}
        hiddenLabel
        id={id}
        inputProps={inputProps}
        onChange={handleChange}
        sx={{ width: '100%' }}
        type="number"
        value={value}
        variant="outlined"
    />
);

}

Here are the issues remaining:

  1. The value in all of the editable cells is defaulted to 0 when the modal opens. The valid values are 0 to (same row's) remaining value. The input validation is working and now the input turns red when the value entered is out of range. However, clicking away or hitting Enter does not complete the cell editing and I would like it to do so. also, I haven't been able to get all of the red outline to show on the input, no matter what i try for styling, the bottom is always cut off.
    image
  2. a single-click in the cell reveals the input, but I would like the input shown prior to the single-click. You said the "cells that are editable have the MuiDataGrid-cell--editable CSS class. You can customize the style targeting this class." I don't know how this works - is there an example you can point me to? It still takes a second click in order to be able to type into the cell, as you stated...

@m4theushw
Copy link
Member

However, it is not obvious that the last column is editable! Would be great if the cells in the last column column could look like this, with the outlined input showing:

This outline only appears when the cell is in edit mode. Basically you need to put all cells from a column in edit mode and this is not supported easily. Entering the edit mode of a cell requires an user interaction (double-click or single-click), but when this step is removed there's a problem when the cell is saved because the default behavior is to return to view mode, however, in this situation we want to stay on edit mode. If it's acceptable I would show an icon on the cells that are editable. You can do this providing a custom edit component. Example:

image

The value in all of the editable cells is defaulted to 0 when the modal opens.

Did you check the initial value in the value prop. About Enter not saving the value, could you provide a CodeSandbox with the full code (including some rows) for us to debug?

a single-click in the cell reveals the input, but I would like the input shown prior to the single-click. You said the "cells that are editable have the MuiDataGrid-cell--editable CSS class. You can customize the style targeting this class." I don't know how this works - is there an example you can point me to? It still takes a second click in order to be able to type into the cell, as you stated...

This is not possible. I explained the reason above. About using the CSS classes, we have some demos in https://mui.com/x/react-data-grid/style/ that may help.

@conerye
Copy link
Author

conerye commented May 5, 2023

OK, thanks for that response! Showing an Edit icon on the cells that are editable it is!
I was able to figure out the rest of the issues too... To close this out, I'll document here what I have done.

*** NOTE preProcessEditCellProps was deleted as it was preventing the cell from exiting edit mode for invalid values

// editable column for export table
{
    field: 'exportCount',
    align: 'left',
    editable: true,
    flex: 1,
    headerAlign: 'left',
    headerName: 'Export',
    renderCell: (params) => {
        return (
            <EditableTextFieldCell
                {...params}
                getErrorValue={() => params.row.licensesAvailable - params.value < 0}
            />
        );
    },
    renderEditCell: (params) => {
        return (
            <TextFieldInputCell
                {...params}
                getErrorValue={() => {
                    const hasError = params?.value
                        ? params.value < 0 || params.value > params.row.licensesAvailable
                        : false;
                    return hasError;
                }}
                inputProps={{ max: params.row.licensesAvailable, min: 0, sx: { py: '5px' } }}
                type="number"
            />
        );
    },
    type: 'number',
}

// custom input
const TextFieldInputCell = ({ field, getErrorValue, id, inputProps, type, value }) => {
const ref = useGridApiContext();

const handleChange = (event) => {
    const newValue = event.target.value;
    ref.current.setEditCellValue({ id, field, value: newValue });
};

return (
    <TextField
        autoFocus
        error={getErrorValue()}
        id={`${id}-${field}-inputCell`}
        inputProps={inputProps}
        onChange={handleChange}
        sx={{ m: 0, width: '100%' }}
        type={type}
        value={value}
        variant="outlined"
    />
);

};

and the latest addition, for the edit icon, EditableTextFieldCell:
displays the cell with value and Edit (pencil) icon on the right side of the cell; sets the cell in edit mode when icon is clicked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: data grid This is the name of the generic UI component, not the React module! support: commercial Support request from paid users
Projects
None yet
Development

No branches or pull requests

3 participants