Search code examples
javascriptreactjschakra-ui

How to populate category and subcategory based on json?


I am creating this admin form, where Category and sub-category will be drop down selection and the options will be from the given Json (categories.json) and the respective sub-category will be populated after selecting category while creating an product. e.g if I select a category_slug men's fashion, then the sub-category such as t-shirt will appear. How to do this on React? the json file

 {
    "categories": [
        {
            "id": "1",
            "name": "Men's Fashion",
            "category_slug": "men's-fashion",
            "category_type": "product",
            "child_categories": [
                {
                    "id": "2",
                    "name": "T-Shirt",
                    "category_slug": "t-shirt"
                },
                {
                    "id": "3",
                    "name": "Panjabi & Fatua",
                    "category_slug": "panjabi-&-fatua"
                },
                {
                    "id": "4",
                    "name": "Polo Shirts",
                    "category_slug": "polo-shirts"
                },
                {
                    "id": "5",
                    "name": "Jeans",
                    "category_slug": "jeans"
                },
                {
                    "id": "6",
                    "name": "Men's Sweaters ",
                    "category_slug": "men's-sweaters-"
                }
            ]
        },
        {
            "id": "7",
            "name": "Electronic Device ",
            "category_slug": "electronic-device-",
            "child_cat": [
                {
                    "id": "8",
                    "name": "Mobile ",
                    "category_slug": "mobile-12"
                },
                {
                    "id": "9",
                    "name": "Tablets",
                    "category_slug": "tablets"
                },
                {
                    "id": "10",
                    "name": "Laptops",
                    "category_slug": "laptops"
                },
                {
                    "id": "11",
                    "name": "Desktops",
                    "category_slug": "desktops"
                },
                {
                    "id": "12",
                    "name": "Gaming Consoles",
                    "category_slug": "gaming-consoles"
                },
                {
                    "id": "13",
                    "name": "Cameras",
                    "category_slug": "cameras"
                },
                {
                    "id": "14",
                    "name": "Security Cameras",
                    "category_slug": "security-cameras"
                },
                {
                    "id": "15",
                    "name": "Test",
                    "category_slug": "test"
                }
            ]
        },
        {
            "id": "16",
            "name": "Electronic Accessories ",
            "category_slug": "electronic-accessories-",
            "child_cat": [
                {
                    "id": "17",
                    "name": "Mobile Accessories",
                    "category_slug": "mobile-accessories"
                },
                {
                    "id": "18",
                    "name": "Wearable",
                    "category_slug": "wearable"
                },
                {
                    "id": "19",
                    "name": "Console Accessories",
                    "category_slug": "console-accessories"
                },
                {
                    "id": "20",
                    "name": "Camera Accessories",
                    "category_slug": "camera-accessories"
                },
                {
                    "id": "21",
                    "name": "Computer Accessories",
                    "category_slug": "computer-accessories"
                },
                {
                    "id": "22",
                    "name": "Storage",
                    "category_slug": "storage"
                },
                {
                    "id": "23",
                    "name": "Printers",
                    "category_slug": "printers"
                },
                {
                    "id": "24",
                    "name": "Computer Components",
                    "category_slug": "computer-components"
                },
                {
                    "id": "25",
                    "name": "Network Components",
                    "category_slug": "network-components"
                },
                {
                    "id": "26",
                    "name": "Software",
                    "category_slug": "software"
                }
            ]
        },
        {
            "id": "27",
            "name": "TV & Home Appliances",
            "category_slug": "tv-&-home-appliances"
        },
        {
            "id": "28",
            "name": "Health & Beauty",
            "category_slug": "health-&-beauty",
            "child_cat": [
                {
                    "id": "29",
                    "name": "Bath & Body",
                    "category_slug": "bath-&-body"
                },
                {
                    "id": "30",
                    "name": "Beauty Tools",
                    "category_slug": "beauty-tools"
                },
                {
                    "id": "31",
                    "name": "Fragrances",
                    "category_slug": "fragrances"
                },
                {
                    "id": "32",
                    "name": "Hair Care",
                    "category_slug": "hair-care"
                },
                {
                    "id": "33",
                    "name": "Makeup",
                    "category_slug": "makeup"
                },
                {
                    "id": "35",
                    "name": "Personal Care",
                    "category_slug": "personal-care"
                },
                {
                    "id": "36",
                    "name": "Skin Care",
                    "category_slug": "skin-care"
                },
                {
                    "id": "5f2a9798e7abc4290b6c6275",
                    "name": "Medical Supplies",
                    "category_slug": "medical-supplies"
                }
            ]
        }
    ]
}

The form. I have used chakraUI for this.

export default function AddProductForm() {
  return (
    <Box display='flex' justifyContent='center' alignItems='center'>
      <Box
        w={[300, 400, 600]}
        border='1px'
        boxShadow='md'
        p={5}
        rounded='md'
        bg='white'
        borderColor='gray.400'
        mx='auto'
      >
        <FormControl id='product' isRequired>
          <FormLabel>Product Name</FormLabel>
          <Input type='text' />
          <FormLabel>Category</FormLabel>   
          <Select>
            <option>United Arab Emirates</option>
            <option>Nigeria</option>
          </Select>
          <FormLabel>Sub-category</FormLabel>
          <Select>
            <option>United Arab Emirates</option>
            <option>Nigeria</option>
          </Select>
          <FormLabel>Description</FormLabel>
          <Input type='text' />
          <FormLabel>Image</FormLabel>
          <Input type='text' />
          <FormLabel>Regular Price</FormLabel>
          <Input type='number' />
          <FormLabel>Sell Price</FormLabel>
          <Input type='number' />
          <FormLabel>Stock Quantity</FormLabel>
          <NumberInput max={5} min={1}>
            <NumberInputField />
            <NumberInputStepper>
              <NumberIncrementStepper />
              <NumberDecrementStepper />
            </NumberInputStepper>
          </NumberInput>
        </FormControl>
      </Box>
    </Box>
  );
}

Solution

  • Use the useState() hook to track value of the parent select. For the child select just find the parent by some unique key (in your case 'id' or 'slug') and map 'child_categories' of the found object as an Option tag.

    Your JSON keys are also inconsistent so fix that.

    Your code should look like this:

    export default function Example() {
      const [parent, setParent] = useState("");
    
      return (
        <div>
          {/* parent */}
          <select value={parent} onChange={(e) => setParent(e.target.value)}>
            <option value=""></option>
            {categories.map((category) => (
              <option value={category.id}>{category.name}</option>
            ))}
          </select>
          {/* child */}
          <select>
            <option value=""></option>
            {categories
              .find((x) => x.id === parent)
              ?.child_categories?.map((category) => (
                <option value={category.id}>{category.name}</option>
              ))}
          </select>
        </div>
      );
    }