Open stamahto opened 2 years ago
I see multiple points in this proposal:
getOptionLabel
I see multiple points in this proposal:
- some DX improvement, like
getOptionLabel
- some UX with the ability to search in long list of options
- new column type with the ability to select multiple items (see [data grid] Add
multipleSelect
column type #4410 for this point)
Yes, you're right. Thank you 👍
The best way is not create column type 'autocomplete', but add functionality to existing ones (i.e. getOptionLabel
can be used for any column type), just add multipleSelect
.
What I haven't mentioned yet is that if I don't define valueOptions
for column type: single/multiSelect, I would expect default options as grouped/unique data from the current column.
This is very common in my practise, also mui-datatables do that for filter type dropdown
Yes, getOptionLabel
could be used for both singleSelect
and a multipleSelect
columns. For other types I don't think so. You rarely expect to see a list of options when entering a date or a number
I'm not sure to fully understand your last point valueOptions
is here to define a finite set of options the user can select. If you do not provide a valueOptions
parameters, it is similar to using string
column type.
I assume your expectation is the API allows you to easily get the array of unique data present in the grid such as you can make them available in an autocomplete.
But that would concern only the filtering aspect
I believe that in many apps, you always have some information according to which you want to group/filter data or just get the most data consistency (including case sensitivity) for something. Imagine, for example, a warehouse where individual items have a manufacturer, type, etc.
Currently, to get these values, I have to manually write for each column something like:
const manufacturers: string[] = useMemo(() => uniq(data.map(m => m.manufacturer)), [data]);
I think this is a much better way to automatically display options than as an empty field, as long as the valueOptions
are not defined in the column.
I really appreciate your time, thank you.
Ok, I better understand the use case.
The technical challenge is to provide access throw the API to the list of unique values. Once done, this list of values could be reused wherever we want: a new custom renderEditCell
or a filterInput
, ...
@alexfauquette we have recently converted to "Pro" and have been tinkering with this problem. I think until this receives the necessary upvotes to get a canonical solution, perhaps a working example in the docs would get us there. I've managed to get us this far:
function AutocompleteEditCell<
T extends { value: string; label: string },
Multiple extends boolean = false,
DisableClearable extends boolean = false,
FreeSolo extends boolean = false
>({
id,
value,
field,
options,
disableClearable,
multiple,
freeSolo,
}: GridRenderEditCellParams & {
options: UseAutocompleteProps<
T,
Multiple,
DisableClearable,
FreeSolo
>['options'];
disableClearable: DisableClearable;
multiple: Multiple;
freeSolo: FreeSolo;
}) {
const apiRef = useGridApiContext();
const handleValueChange = (
_: any,
newValue: AutocompleteValue<T, Multiple, DisableClearable, FreeSolo>
) => {
apiRef.current.setEditCellValue({
id,
field,
// @ts-expect-error i can't figure out how to use AutocompleteValue
value: typeof newValue === 'string' ? value : newValue?.value || '',
});
};
return (
<Autocomplete<T, Multiple, DisableClearable, FreeSolo>
fullWidth
disableClearable={disableClearable}
multiple={multiple}
options={options}
freeSolo={freeSolo}
// @ts-expect-error i can't figure out how to use AutocompleteValue
value={options.find((o) => o.value === value)?.label || ''}
onChange={handleValueChange}
renderInput={(params) => <TextField {...params} />}
/>
);
}
and this is referenced thusly:
{
field: 'naicsCode',
headerName: 'Industry',
width: 250,
editable: true,
valueFormatter: ({ value }) => NAICS_OBJECT[value] ?? ''
renderEditCell: (params) => (
<AutocompleteEditCell
{...params}
options={NAICS_OPTIONS}
freeSolo={false}
multiple={false}
disableClearable
/>
),
},
First, if you see anything obvious we could be doing to clear up those two @ts-expect-error
s I'd love your eyes on those! But more broadly for this task, it seems like something to this effect could go into the docs to explain how to do it manually? Similar to https://mui.com/x/react-data-grid/editing/#usage-with-mui-x-date-pickers perhaps?
Thanks @adamrneary for example. It's been a while so I have written solution too. Here is my example:
import { Autocomplete, TextField } from "@mui/material";
import { GridRenderEditCellParams, useGridApiContext } from "@mui/x-data-grid-pro";
import { useCallback } from "react";
interface AutocompleteEditInputCellProps {
params: GridRenderEditCellParams,
options: any[] | undefined,
freeSolo?: boolean,
multiple?: boolean,
getOptionLabel?: (option: any) => string
}
export function AutocompleteEditInputCell(props: AutocompleteEditInputCellProps) {
const { params, options, freeSolo, getOptionLabel, multiple } = props;
const apiRef = useGridApiContext();
const handleChange = useCallback((event: React.SyntheticEvent<Element, Event>, newValue: any) => {
event.stopPropagation();
apiRef.current.setEditCellValue({ id: params.id, field: params.field, value: newValue });
}, [params.id, params.field]);
const getValue = useCallback(() => {
if (params.value)
return params.value;
if (multiple)
return [];
return null;
}, [params.value, multiple]);
return (
<Autocomplete
value={getValue()}
onChange={handleChange}
onInputChange={(event, value) => (freeSolo && !multiple && event) && handleChange(event, value)}
fullWidth
multiple={multiple}
options={options ?? []}
freeSolo={freeSolo}
autoHighlight
getOptionLabel={getOptionLabel}
renderInput={(inputParams) => <TextField {...inputParams} error={params.error} />}
/>
);
}
In function handleChange
needs to be event.stopPropagation();
to succesfully handle selection from open list values by hitting enter, otherwise it would close edited row without value selection.
Yes, I am using Autocomplete in 4 columns in a grid, since it is far better for large drop down lists since it allows user to search from the list by entering first few characters. Though I need single option select only. My Upvote.
On the other note:- I have done custom component setup as suggested in docs and similar to what @stamhato has done, and it has been working like charm till "@mui/x-data-grid-pro": "5.16.0",
When I upgrade my data-grid-pro version to 5.17.1
it starts malfunctioning, the moment the focus goes in the autocomplete cell, my processRowUpdate
get triggered and the row got saved.
To save from this bug, I have reverted back to 5.16.0.
I am not sure if I should be logging a new issue for this or if this comment of mine will catch the attention of the material-ui team. Ref Order ID 💳 (optional) 28914
@adamrneary You should open another issue with a minimal reproduction of your customization that bugs in v5.17.1
Otherwise, this bug/regression will be lost into other comments asking for feature
I agree with the UX recommendation made by the author of this issue. I think that it could be great to replace most uses of Select
for an Autocomplete
, I assume that it would yield a better UX for end-users.
IMHO, the only question is: Should we always use the Autocomplete
over the Select
?
Airtable said yes. Notion said no: use a Select if there are always fewer than 5 options.
For example with the singleSelect
column type edit mode: :100: to replace the default Select to have an Autocomplete, like done by these:
Notion (singleSelect):
Airtable (singleSelect):
Google spreadsheet
I agree with the UX recommendation made by the author of this issue. I think that it could be great to replace most uses of
Select
for anAutocomplete
, I assume that it would yield a better UX for end-users.IMHO, the only question is: Should we always use the
Autocomplete
over theSelect
? Airtable said yes. Notion said no: use a Select if there are always fewer than 5 options.
Well, I don't know the answer either, but here are some of my thoughts:
singleSelect
, multiSelect
, singleAutocomplete
, multiAutocomplete
)I know its a lot to ask but can anyone provide me a snippet of a working autocomplete functionality inside a cell in the datagrid. I am unable to implement it
I know its a lot to ask but can anyone provide me a snippet of a working autocomplete functionality inside a cell in the datagrid. I am unable to implement it
My code few comments up here is updated and works pretty well: https://github.com/mui/mui-x/issues/4813#issuecomment-1190009699
The usage is: renderEditCell: params => <AutocompleteEditInputCell params={params} options={["A", "B"]} />
I got it to work like this:
import { useState } from "react";
import { DataGrid } from "@mui/x-data-grid";
const UserPage = () => {
const [users, setUsers] = useState([
{ id: 1, name: "John Doe", email: "john@example.com", role: "basic" },
{ id: 2, name: "Jane Smith", email: "jane@example.com", role: "admin" },
// Add more user objects as needed
]);
const handleRoleChange = (event, id) => {
const newUsers = [...users];
const userIndex = newUsers.findIndex((user) => user.id === id);
if (userIndex !== -1) {
newUsers[userIndex].role = event.target.value;
setUsers(newUsers);
console.log(newUsers);
}
};
const columns = [
{ field: "name", headerName: "Name", width: 150 },
{ field: "email", headerName: "Email", width: 200 },
{
field: "role",
headerName: "Role",
width: 120,
type: "singleSelect",
valueOptions: ["basic", "admin"],
editable: true,
},
];
return (
<div style={{ height: 400, width: "100%" }}>
<DataGrid rows={users} columns={columns} />
</div>
);
};
export default UserPage;
Now it works how you would expect. The cells becomes autocomplete type elements when you start editing them. But now I'm having slight trouble in handling the change. Any idea on how to track change here?
Have a problem when used an Autocomplete inside DataGrid MUI
I gave a code snippet above. That works
@AXLShorts Thk, this issue is solved
Have a problem when used an Autocomplete inside DataGrid MUI
![]()
@hcurbelo-hepyco I also have same issue where in system displays [object Object] using autocomplete inside mui data grid edit mode
Update:
Was able to manage it via renderCell method to display value from object.
For what it's worth, setting renderCell
and renderEditCell
to the autocomplete box with editable
seems to work fine for the community version for me.
I got it to work like this:
import { useState } from "react"; import { DataGrid } from "@mui/x-data-grid"; const UserPage = () => { const [users, setUsers] = useState([ { id: 1, name: "John Doe", email: "john@example.com", role: "basic" }, { id: 2, name: "Jane Smith", email: "jane@example.com", role: "admin" }, // Add more user objects as needed ]); const handleRoleChange = (event, id) => { const newUsers = [...users]; const userIndex = newUsers.findIndex((user) => user.id === id); if (userIndex !== -1) { newUsers[userIndex].role = event.target.value; setUsers(newUsers); console.log(newUsers); } }; const columns = [ { field: "name", headerName: "Name", width: 150 }, { field: "email", headerName: "Email", width: 200 }, { field: "role", headerName: "Role", width: 120, type: "singleSelect", valueOptions: ["basic", "admin"], editable: true, }, ]; return ( <div style={{ height: 400, width: "100%" }}> <DataGrid rows={users} columns={columns} /> </div> ); }; export default UserPage;
Now it works how you would expect. The cells becomesg autocomplete type elements when you start editing them. But now I'm having slight trouble in handling the change. Any idea on how to track change here?
who is calling handleRoleChange and how does it know to di it?
Summary 💡
Should work like normal Autocomplete component. Unlike 'singleSelect', users can type in input and search options quickly.
Examples 🌈
Motivation 🔦
Autocomplete provides more freedom for users and also developers than select (singleSelect), like: freeSolo, getOptionLabel or multiple props.
Order ID 💳 (optional)
31956