Search code examples
reactjsselectmaterial-uimenuitem

Select Menu isn't getting value from it's sub Menu Item


What I'm trying to do

I'm trying to create a category list with Material UI

  • Parent Menu Item
  • Child Menu Item by Parent Menu Category

What I'm getting

  • I'm getting only parent menu value.
  • Whenever I click on child item, than it showing it's parent Menu.

Code

Here I've create a codesanbox, Please help to get out from this.

  • Code
  • Please check console for see event.

<Select
          displayEmpty
          defaultValue=""
          value={search}
          onChange={handleChange}
          id="grouped-select"
          input={<OutlinedInput />}
          label="Category"
          size="small"
          sx={{
            width: "160px",
            height: "100%",
            borderRadius: 0,
            textTransform: "uppercase"
          }}
          renderValue={(selected) => {
            if (selected.length === 0) {
              return (
                <Typography variant="subtitle2">Select Category</Typography>
              );
            }
            return <Typography variant="subtitle2">{selected}</Typography>;
          }}
        >
          <MenuItem value="select category">
            <Typography variant="subtitle2">Select Category</Typography>
          </MenuItem>

          {categories.map((category) => (
            <MenuItem
              key={category}
              sx={{
                lineHeight: "20px",
                display: "block",
                backgroundColor: "none"
              }}
              value={category}
            >
              <Typography variant="subtitle2">{category}</Typography>

              {category === "Baby Products" &&
                babyProducts.map((item) => (
                  <List key={item} sx={{ padding: 0 }}>
                    <MenuItem
                      sx={{
                        lineHeight: "12px",
                        display: "block"
                      }}
                      value={item}
                      onChange={handleChange}
                    >
                      <Typography variant="subtitle2">{item}</Typography>
                    </MenuItem>
                  </List>
                ))}
            </MenuItem>
          ))}
        </Select>

const babyProducts = [
  "Baby",
  "Baby Cereal",
  "Baby Honey",
  "Biscotti",
  "Formula",
  "Milk",
  "Juice",
  "Puree",
  "Bath & Skincare",
  "Diapers & Wipes",
  "Huggies",
  "Kidz",
  "MamyPoko",
  "Molfix",
  "Pampers & Wipes",
  "Oral Care",
];

const chocolates = [
  "Assorted",
  "Cadbury",
  "Candy",
  "Chocolate Balls",
  "Chocolate Bars",
  "Kit-Kat",
  "Lolipops",
  "Marshmallow",
  "Mints&Gums",
  "Toblenore",
];


Solution

  • The problem is due to nested MenuItems. You can use nested arrays instead with the marginLeft on a subcategory:

    {categories.map((cat) => [
      renderCategory(cat),
      renderCategoryItems(cat)
    ])}
    
    const renderCategory = (category) => {
      return (
        <MenuItem
          key={category}
          sx={{
            lineHeight: "20px",
            display: "block",
            backgroundColor: "none"
          }}
          value={category}
        >
          <Typography variant="subtitle2">{category}</Typography>
        </MenuItem>
      );
    };
    
    const renderCategoryItems = (category) => {
      const list = category === "Baby Products" ? babyProducts : [];
      return list.map((item) => (
        <MenuItem
          key={item}
          sx={{
            lineHeight: "12px",
            display: "block"
          }}
          value={item}
        >
          <Typography
            sx={{
              marginLeft: "16px"
            }}
            variant="subtitle2"
          >
            {item}
          </Typography>
        </MenuItem>
      ));
    };
    

    Update

    If more subcategories are required, you can describe them as follows:

    const subCategories = {
      "Baby Products": [
        ...
      ],
      "Chocolate": [
        ...
      ]
    };
    

    And update renderCategoryItems function:

    const list = subCategories[category] || [];
    

    Working example