How to Create a Material-UI Treeview with Styled Checkboxes

I was recently researching what to write about next and discovered that quite a few people are interested in adding checkboxes to the Material-UI Treeview component. In this Material-UI Issues thread, user dnquang1996vn shared a great Code Sandbox he created.

In this post, I will dive into his code for the following reasons:

  1. It’s better than the Treeview with checkboxes Code Sandbox on page one of Google (at time of writing this) and I can get his code more visibility.
  2. In the Issues thread, there were questions about how his code worked. It’s excellent code and a good to explore.
  3. I forked his sandbox and added some custom checkbox styling.

Forked Code Sandbox with full React code is in the Resources section.

Checkbox JSX

Injecting a component into a Treeview can be done simply by passing the component as the Treeview label prop.

Take a look at a simplified version of the code below:

<TreeItem
  label={
    <FormControlLabel
      control={
        <Checkbox
 />
      }
    </FormControlLabel>
  }
/>

Label is a common prop in Material-UI. Normally we may think of labels as text only, but MUI often gives flexibility to pass objects and uniquely customize a user interface.

Programmatically Selecting Children Checkboxes

The selection logic has three steps to it:

  1. Get the object representation of the node that was selected
  2. Get an array of the string ids of the selected node and all of its children
  3. Add these nodes to the array of previously selected checkboxes OR filter these nodes out of the previously selected (on uncheck click)

In my sandbox I left the code from the original author mostly unchanged but added code comments similar to the above steps. The selection logic is complex; there is lots of array destructuring and recombining, filtering, and other array functionality.

I encourage you to take a look. The code is written efficiently and you might pick up some good programming techniques.

Event Propagation

Let’s take a look at the Checkbox JSX:

<Checkbox
  checked={selected.some((item) => item === nodes.id)}
    onChange={(event) =>
      getOnChange(event.currentTarget.checked, nodes)
    }
    onClick={(e) => e.stopPropagation()}
    className={classes.checkbox}
/>

Notice that it’s the onChange handler that kicks off the selection logic.

The onClick prop, on the other hand, simply receives a small function that stops event propagation. Without this, the Treeview expands and contracts when checkboxes are clicked. Remember, the checkbox is actually the label for each Treeview node. Try commenting the onClick prop out to see the difference.

Styling Checkboxes

In the code snippet above, the Checkbox component is given class checkbox. This was not in the original sandbox but I have added it since it can be difficult to get the selectors correct when styling MUI components.

const useStyles = makeStyles((theme) => ({
  checkbox: {
    "&.MuiCheckbox-root": {
      color: "rgba(81, 185, 201, 0.8)"
    },
    "&.MuiCheckbox-colorSecondary": {
      "&.Mui-checked": {
        color: "rgba(160, 81, 201, 1)"
      }
    }
  }
}));

MuiCheckbox-root is part of the global styling API in Material-UI. It is added to all MUI Checkbox components. MuiCheckbox-colorSecondary is also part of the global styling API, but it is auto-added only when the Checkbox component is selected.

This image of the DOM gives useful insight into MUI styling:

Notice both classes exist on the span generated by Material-UI.

Explore the Checkbox css API for more styling options.

Resources:

Think you’re a JavaScript expert? Test yourself on these 50 difficult JavaScript questions.

Are you looking for training in Material-UI? Check out my review of the 3 best Material-UI courses in Udemy, including my top pick with 40+ hours of training content.

Checkboxes are highly versatile and can be added to many components. Take a look at adding styled Checkboxes to the Select Component or using Checkboxes in a Transfer List.

Code Sandbox:

Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.