Search code examples
javascriptcssnext.jsmaterial-uitreeview

How to select a parent element in tree and not lose child's 'selected' styles


I have a MUI TreeView component with a nested mapping of Categories (parent) and Articles (Child). When I select a child, that child has styles applied to it based on "selected". When I click a parent, the previous child loses its "selected" styles.

How can I make a differentiation between "child selected" and "parent clicked(selected)".

I would prefer to do this all in CSS if possible. This is a Next.js app.

My CategoryItem CSS:

const StyledCategoryItemRoot = styled(TreeItem)(({ theme }) => ({
  [`& .${treeItemClasses.content}`]: {
    fontWeight: theme.typography.fontWeightBold,
    marginBottom: 5,
    paddingLeft: 0,
    borderRadius: theme.shape.borderRadius,
    '&.Mui-selected.Mui-focused, &:hover, &.Mui-selected:hover': {
      backgroundColor:
        theme.palette.mode === 'light'
          ? alpha('#ff9aff', 0.16)
          : alpha('#2f506f', 0.24),
    },
    '&.Mui-selected, &.Mui-focused': {
      backgroundColor: 'transparent',
    },
  },
}));

My ArticleItem CSS:

const StyledArticleItemRoot = styled(TreeItem)(({ theme, router, post }) => ({
  color:
    theme.palette.mode === 'light'
      ? theme.palette.grey[900]
      : theme.palette.grey[500],
  [`& .${treeItemClasses.content}`]: {
    fontWeight: theme.typography.fontWeightBold,
    paddingLeft: 0,
    borderRadius: theme.shape.borderRadius,
    transition: '.2s',
    '&.Mui-selected:hover, &.Mui-selected.Mui-focused:hover, &:hover': {
      color: theme.palette.mode === 'light' ? theme.palette.grey[800] : 'white',
    },
    '&.Mui-focused, &.Mui-selected, &.Mui-selected.Mui-focused': {
      backgroundColor:
        theme.palette.mode === 'light'
          ? alpha('#ff9aff', 0.16)
          : alpha('#2f506f', 0.16),
      color:
        post.attributes.slug !== router.query.slug
          ? theme.palette.grey[500]
          : theme.palette.mode === 'light'
          ? theme.palette.primary.main
          : theme.palette.secondary.main,
    },
  },
}));

Solution

  • in MUI tree view component ,if multiselect is off multiSelect={false} you can only select one node (parent or child), you can't selected both parent and child at same time!

    so if you selected child node then selected parent node , the child will lose selected node style because it is not selected anymore !

    Answering ur question in comments :

    I want to be able to click the Categories dropdown without losing the "selected" styling on Article.

    what u can do this by: handling selection of nodes manually

    <TreeView
       aria-label="file system navigator"
       key="treeView"
       defaultCollapseIcon={<ExpandMoreIcon />}
       defaultExpandIcon={<ChevronRightIcon />}
       multiSelect={false}
       selected={selectedNodes}
       onNodeSelect={(e, node_ids) => {
         handleClick(e, node_ids);
       }}> //add here tree nodes 
    </TreeView>
    

    NOW in handleClick function , you will set the selected nodes :

    setSelectedNodes(nodes_ids);
    

    AND to make it ONLY selected if the clicked element is the node label and NOT the dropdown NOR the collapsable icon

    so the handleClick will look like this :

     function handleClick(e, nodes_ids) {
      if (e.target.className == "MuiTreeItem-label") 
       setSelectedNodes(nodes_ids);
    }
    

    ps : don't forget to add selectedNodes to ur state :

    [selectedNodes, setSelectedNodes]=useState([]);