Material-UI TreeView - How to get the nodeId of the TreeItem that was clicked on?

Viewed 2806

I am using Material UIs Tree View, and I would like to get the props, or nodeId, of the item when the icon is clicked. How does one do that? Basically, I want to have a delete icon, that will call an API to delete the node based on its ID.

In their example, they are passing props to MinusSquare and PlusSquare but when I console.log those props they are empty.

function MinusSquare(props) {
 return (
   <SvgIcon fontSize="inherit" style={{ width: 14, height: 14 }} {...props}>
    ...
   </SvgIcon>
 );
}
...
<TreeView
  aria-label="customized"
  className={classes.root}
  defaultExpanded={['1']}
  defaultCollapseIcon={<MinusSquare />}
  defaultExpandIcon={<PlusSquare />}
  defaultEndIcon={<CloseSquare />}
>
  <StyledTreeItem nodeId="1" label="Main"> <!--- get these nodeId values and/or other props --->
    <StyledTreeItem nodeId="2" label="Hello" />
    <StyledTreeItem nodeId="3" label="Subtree with children">
      <StyledTreeItem nodeId="6" label="Hello" />
      <StyledTreeItem nodeId="7" label="Sub-subtree with children">
        <StyledTreeItem nodeId="9" label="Child 1" />
        <StyledTreeItem nodeId="10" label="Child 2" />
        <StyledTreeItem nodeId="11" label="Child 3" />
      </StyledTreeItem>
      <StyledTreeItem nodeId="8" label="Hello" />
    </StyledTreeItem>
    <StyledTreeItem nodeId="4" label="World" />
    <StyledTreeItem nodeId="5" label="Something something" />
  </StyledTreeItem>
</TreeView>
1 Answers

Material-UI 4.9.13 adds onIconClick props to the TreeItem. Since every TreeItem needs to attach a click listener, you should write a wrapper component to reuse the code:

function MyTreeItem(props) {
  return (
    <TreeItem
      {...props}
      onIconClick={() => console.log('delete', props.nodeId)}
    />
  );
}

Unfortunately, this props was removed in Material-UI 5.0.0 alpha-12 in favor of ContentComponent. This API requires you to write significantly more code, in exchange of more flexible customization:

import Typography from "@material-ui/core/Typography";
import IconButton from "@material-ui/core/IconButton";
import DeleteIcon from "@material-ui/icons/Delete";
import TreeView from "@material-ui/lab/TreeView";
import TreeItem, { useTreeItem } from "@material-ui/lab/TreeItem";
import clsx from "clsx";

const CustomContent = React.forwardRef(function CustomContent(props, ref) {
  const {
    classes,
    label,
    nodeId,
    icon: iconProp,
    expansionIcon,
    displayIcon,
    onDelete
  } = props;

  const {
    disabled,
    expanded,
    selected,
    focused,
    handleExpansion,
    handleSelection,
    preventSelection
  } = useTreeItem(nodeId);

  const icon = iconProp || expansionIcon || displayIcon;
  const handleDelete = () => onDelete(nodeId);

  return (
    <div
      className={clsx(classes.root, {
        [classes.expanded]: expanded,
        [classes.selected]: selected,
        [classes.focused]: focused,
        [classes.disabled]: disabled
      })}
      onMouseDown={preventSelection}
      ref={ref}
    >
      <div onClick={handleExpansion} className={classes.iconContainer}>
        {icon}
      </div>
      <IconButton size="small" onClick={handleDelete}>
        <DeleteIcon fontSize="small" />
      </IconButton>
      <Typography
        onClick={handleSelection}
        component="div"
        className={classes.label}
      >
        {label}
      </Typography>
    </div>
  );
});

TreeItem

function MyTreeItem(props) {
  return (
    <TreeItem
      {...props}
      ContentComponent={CustomContent}
      ContentProps={{
        onDelete: (nodeId) => console.log("delete", nodeId)
      }}
    />
  );
}

TreeView

<TreeView
  defaultCollapseIcon={<ExpandMoreIcon />}
  defaultExpandIcon={<ChevronRightIcon />}
  multiSelect
>
  <MyTreeItem nodeId="1" label="Applications">
    <MyTreeItem nodeId="2" label="Calendar" />
    <MyTreeItem nodeId="3" label="Chrome" />
    <MyTreeItem nodeId="4" label="Webstorm" />
  </MyTreeItem>
  <MyTreeItem nodeId="5" label="Documents">
    <MyTreeItem nodeId="6" label="Material-UI">
      <MyTreeItem nodeId="7" label="src">
        <MyTreeItem nodeId="8" label="index.js" />
        <MyTreeItem nodeId="9" label="tree-view.js" />
      </MyTreeItem>
    </MyTreeItem>
  </MyTreeItem>
</TreeView>

Live Demo

Edit ControlledTreeView Material Demo (forked)

Related