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

[data grid] Add multipleSelect column type #4410

Open
2 tasks done
linojon opened this issue Apr 8, 2022 · 8 comments
Open
2 tasks done

[data grid] Add multipleSelect column type #4410

linojon opened this issue Apr 8, 2022 · 8 comments
Labels
component: data grid This is the name of the generic UI component, not the React module! design This is about UI or UX design, please involve a designer new feature New feature or request waiting for 👍 Waiting for upvotes

Comments

@linojon
Copy link

linojon commented Apr 8, 2022

Order ID 💳

41465

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

The problem in depth 🔍

I have a column that contains a list of tag names. Presently I render using rowItem.tagNames.join(' '). But I also want to filter with a select list rather than simple strings. When I define the column as type: 'singleSelect' and define the valueOptions with existing tag names, this works when a row has just one tag. How can i set up the column for cells to contain more than one tag. (Filtering on just one of the tags at a time is fine).

Benchmark

  • Notion

Screenshot 2023-03-28 at 12 41 38

Screenshot 2023-03-28 at 12 42 23

  • Airtable

Screenshot 2023-03-28 at 12 43 24

Screenshot 2023-03-28 at 12 43 39

Similar requests

@linojon linojon added status: waiting for maintainer These issues haven't been looked at yet by a maintainer support: commercial Support request from paid users labels Apr 8, 2022
@alexfauquette alexfauquette added support: question Community support but can be turned into an improvement and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Apr 11, 2022
@alexfauquette
Copy link
Member

Hi, here is a draft solution. The following demo has a column 'discount' which is a single select allowing multiple tags

https://codesandbox.io/s/columntypesgrid-material-demo-forked-4bbcrv?file=/demo.js

  • The valueFormatter is used to map from the array of stages to a string
  • The renderEditCell is customized to allow multiple values
  • The filter input are updated, because valueOptions are also formated, which is not the expected behavior in this particular case
  • The filter methods are updated to support columns containing an array
valueFormatter: ({ value }) => (value ? value.join("/") : ""),
renderEditCell: CustomDiscountEditCell,
filterOperators: [
  {
    value: "contains",
    getApplyFilterFn: (filterItem) => {
      if (filterItem.value == null || filterItem.value === "") {
        return null;
      }
      return ({ value }) => {
        // if one of the cell values corresponds to the filter item
        return value.some((cellValue) => cellValue === filterItem.value);
      };
    },
    InputComponent: CustomFilterInputSingleSelect
  }
]

@m4theushw m4theushw added the waiting for 👍 Waiting for upvotes label Apr 11, 2022
@m4theushw
Copy link
Member

I added the "waiting for 👍" label. If this gets enough votes we can add a new column type based on singleSelect. The reason that singleSelect has this name is to give room for a "multiple" option. Related to #1956 (comment)

@m4theushw m4theushw changed the title [question] column type for list of tags? [data grid] Add multipleSelect column type Apr 11, 2022
@linojon
Copy link
Author

linojon commented Apr 13, 2022

works great. Thanks! (do i leave this open?)

BTW i also needed to add a corresponding GridComparatorFn :)

@alexfauquette
Copy link
Member

Yes, leave it open such that we can track upvotes or any comments.

You have to provide a custom function to sortComparator

If you need some inspiration, the default column definitions of each type are in the x-data-grid/src/codDef' folder

@iddan
Copy link

iddan commented Jun 2, 2022

My team is on the Pro plan and we would really like this.

@joserodolfofreitas joserodolfofreitas added the component: data grid This is the name of the generic UI component, not the React module! label Sep 28, 2022
@oliviertassinari oliviertassinari removed support: question Community support but can be turned into an improvement support: commercial Support request from paid users design: ui labels Mar 28, 2023
@oliviertassinari oliviertassinari added design This is about UI or UX design, please involve a designer and removed design: ux labels Aug 18, 2023
@tibo-glamarche
Copy link

My team and I are on the pro plan and would like to have this !

@PunkFleet
Copy link

Hi, here is a draft solution. The following demo has a column 'discount' which is a single select allowing multiple tags

https://codesandbox.io/s/columntypesgrid-material-demo-forked-4bbcrv?file=/demo.js

  • The valueFormatter is used to map from the array of stages to a string
  • The renderEditCell is customized to allow multiple values
  • The filter input are updated, because valueOptions are also formated, which is not the expected behavior in this particular case
  • The filter methods are updated to support columns containing an array
valueFormatter: ({ value }) => (value ? value.join("/") : ""),
renderEditCell: CustomDiscountEditCell,
filterOperators: [
  {
    value: "contains",
    getApplyFilterFn: (filterItem) => {
      if (filterItem.value == null || filterItem.value === "") {
        return null;
      }
      return ({ value }) => {
        // if one of the cell values corresponds to the filter item
        return value.some((cellValue) => cellValue === filterItem.value);
      };
    },
    InputComponent: CustomFilterInputSingleSelect
  }
]

It's very effective but doesn't work for situations with tons of options. I used autoComplete for this in v5, and now that I've updated some of the details I find that it still works:

const CategoryCell = (props: GridRenderCellParams) => {
    const {id, value, field} = props;
    const apiRef = useGridApiContext();
    const [dataSet, setDataSet] = useState<any[]>([])
    useEffect(()=>{
        const category = [
            {id:1, name: 'Technology'},
            {id:2, name: 'Business'},
            {id:3, name: 'Fintech & Finance'},
            {id:4, name: 'AI & IOT'}
        ];
        setDataSet(category);
    },[])
    const handleChange:any = async (event: SelectChangeEvent,item:any) => {
        const isValid = await apiRef.current.setEditCellValue({ id, field, value: item });
        if (isValid) {
            apiRef.current.stopCellEditMode({ id, field });
        }
    };
    const handleDelete = (index:number) => {
        const updatedValue = [...value];
        // Remove the item at the specified index
        updatedValue.splice(index, 1);
        // Update the state with the new value array
        handleChange(null, updatedValue);
    };
    return (
        <Autocomplete fullWidth value={value} multiple limitTags={3}
                      options={dataSet}
                      getOptionLabel={(option: any) => option.name}
                      filterSelectedOptions
                      onChange={handleChange}
                      renderInput={(params)=> (
                          <TextField {...params} placeholder="Choose Category" />)
                    }
                    isOptionEqualToValue={(option, value) => option.id === value.id}
                    renderTags={(value) => (
                        <Stack direction="row" spacing={1}>
                            {value.map((option,index) => (
                                <Chip
                                    key={index}
                                    label={option.name}
                                    onDelete={()=>handleDelete(index)}
                                />
                            ))}
                        </Stack>
                    )}
                        
        />

    )
}

calling this like this:

    const editCategory: GridColDef['renderCell'] = (params) => {
        return (
            <CategoryCell {...params} />
        )
    }
    const columns: GridColDef[] = [
    { field: 'category', headerName: 'Categories', width: 400, editable: true,            
            renderCell: (params) => {
                return <Stack direction="row" spacing={1}>
                    {params.value.map((item:any)=> (
                        <Chip key={item.id} label={item.name} />
                    ))}
                </Stack>
            },
            renderEditCell: editCategory,
        },
]    

@uixrob
Copy link

uixrob commented Mar 25, 2024

image

+1 something like this for the data grid would increase the user experience for multi filtering on a column

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! design This is about UI or UX design, please involve a designer new feature New feature or request waiting for 👍 Waiting for upvotes
Projects
None yet
Development

No branches or pull requests

9 participants