Is it possible to allow only one expanded row in a datagrid?

Viewed 241

I would like to only allow my users to have one row expanded at a time. With a default Datagrid you can expand as many rows as you like, increasing the vertical space taken along with increasing the amount of data shown on the screen.

Assuming there is no default setting (i have not found one), I think the only way to make this happen is by manually adjusting the state in the Redux store. I can see the state within the redux store here:

redux store showing my expanded list state

I am pretty weak in Redux and I am not sure the best way to go about ensuring that there is only one value in the "expanded" array. Does anyone have any ideas for me to try? Thanks in advance!

1 Answers

I surprised myself by trial-and-erroring my way to a solution. Basically I used useSelector to get the state of what is expanded in my list, and then set up an effect to watch for when that array changes. If the array is larger than one, I simply toggle the first item in the array with useDispatch.

Code snippet:

    const expanded  = useSelector(state => 
        state.admin.resources.PackageInfo.list.expanded
    );

    const dispatch = useDispatch();

    useEffect(() => {
      if(expanded.length > 1) 
        dispatch(toggleListItemExpand('PackageInfo', expanded[0]));
    }, [expanded]);

I am curious to get any feedback on this, I am not sure what the side-effects or consequences of custom dispatches to the store will be. I think tomorrow I will try to expand this into a reusable hook that I can use in all of my lists.

EDIT:

I did move this into a hook and have it working in multiple lists now. Here is the full hook:

    import { useEffect } from "react";
    import { useSelector, useDispatch } from "react-redux";
    import { toggleListItemExpand } from "react-admin";
        
    const useExpandOnlyOne = (resource) => {
      const expanded = useSelector(
        (state) => state.admin.resources[resource].list.expanded
      );
      const dispatch = useDispatch();
    
      useEffect(() => {
        if (expanded.length > 1)
          dispatch(toggleListItemExpand(resource, expanded[0]));
      }, [expanded]);
    };
    
    export default useExpandOnlyOne;

I simply call it in my lists at the top level like this:

    const PackageList = (props) => {
        useExpandOnlyOne(props.resource);
    ....
Related