Search code examples
reactjsbootstrap-material-designmdbreact

Drop down based on selection of the first drop down using a MDB-reactjs


This question may sound like a duplicate one when you have so many examples in StackOverflow about react drop-down based on other drop-down. For some weird reason, I am not able to fix the problem in my code. I am not quite sure whether this is happening because of the MDBreact framework. I am fairly new to react as well. guys any help will be greatly appreciated.

import React, { Component } from "react";
import {
  MDBContainer,
  MDBBtn,
  MDBModal,
  MDBModalBody,
  MDBModalHeader,
  MDBModalFooter
} from "mdbreact";


import "../../App.css";

class ModalInvenAddItems extends Component {
  constructor(props) {
    super(props);
    this.state = {
      modal: false,
      tools: [
        {
          name: "machine",
          lists: [
            "Lathe",
            "Milling m/c",
            "drillingm/c",
            "hand grinder",
            "hand drill",
            "pedestal grinder",
            "belt sander",
            "hand chainsaw  ",
            "Angle Grinder"
          ]
        },
        {
          name: "Hand-tools",
          lists: [
            "spanners",
            "screw drivers",
            "hammers",
            "allenkeys",
            "punch",
            "hacksaw",
            "files",
            "pliers",
            "center punches",
            "scribes"
          ]
        },
        {
          name: "cutting-tools",
          lists: [
            "Auger Bits",
            "Taper shank Twist drill",
            "strisght shank Twist drill",
            "Countersink Drills",
            "mill cutters",
            "lathe tools",
            "taps",
            "threadcutting tools",
            "oil stones",
            "emery papers"
          ]
        },
        {
          name: "Measurment-Instruments",
          lists: [
            "vernier-calipers",
            "ruler",
            "compass",
            "x-callipers",
            "spirit level",
            "tape"
          ]
        },
        {
          name: "cleaning-tools",
          lists: ["brushes", "Dustbins", "Vacuum Cleaner", "Rugs","Dustpans "]
        },
        {
          name: "fastners",
          lists: [
            "screws",
            "wood screws",
            "machine screws",
            "thread cutting m/c screws",
            "nuts",
            "Hex",
            "heavy hex",
            "flange",
            "washers",
            "flat",
            "fender",
            "external tooth lock",
            "split lock",
            "internal Tooth lock",
            "bolts",
            "revet"
          ]
        },
        {
          name: "fluids",
          lists: ["cutting oil", "lubrication", "glues"]
        },
        {
          name: "Clamping-tools",
          lists: [
            "F-clamps",
            "bar-clamps",
            "c-clamps",
            "vices",
            "t-bolts",
            "step blocks",
            "parallel blocks"
          ]
        },
        {
          name: "safety-equipments",
          lists: ["goggles", "ear-muffs"]
        }
      ],
      selectedCategory: "select the category",
      selectedList: []
    };
    this.toggle = this.toggle.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }

  toggle = () => {
    this.setState({
      modal: !this.state.modal
    });
  };

  handleChange(e) {
    this.setState({ selectedCategory: e.target.value });
  }

  render() {
    let divstyle = {
      color: "blue",
      fontStyle: "italic",
      fontWeight: "semi-bold"
    };

    let toolgroup = this.state.tools.filter(tool => {
      return tool.name === this.state.selectedCategory;
    });

    return (
      <MDBContainer>
        <a
          style={divstyle}
          className="btnadditem"
          title="Add new items"
          onClick={this.toggle}
        >
          <i className="fas fa-plus" />
        </a>
        <MDBModal
          id="modalAdditems"
          isOpen={this.state.modal}
          toggle={this.toggle}
        >
          <MDBModalHeader toggle={this.toggle}>
            Add new Inventory Item
          </MDBModalHeader>
          <MDBModalBody>
            <div className="form-group">
              <label>Description</label>
              <input type="email" className="form-control invModal" />
              <label>Category</label>
              <div>
                <select
                  className="browser-default custom-select"
                  onChange={this.handleChange}
                  value={this.state.selectedCategory}
                >
                  {this.state.tools.map((toolCategory, i) => {
                    return <option key={i}>{toolCategory.name}</option>;
                  })}
                </select>
              </div>
              <div>
                <select>
                  {toolgroup[0].lists.map((list, i) => {
                    return <option key={i}>{list}</option>;
                  })}
                </select>
              </div>
            </div>
          </MDBModalBody>
          <MDBModalFooter>
            <MDBBtn color="secondary" onClick={this.toggle}>
              Close
            </MDBBtn>
            <MDBBtn color="primary" onClick={this.postdata}>
              Save changes
            </MDBBtn>
          </MDBModalFooter>
        </MDBModal>
      </MDBContainer>
    );
  }
}

export default ModalInvenAddItems;

The error that I am receiving is "TypeError: Cannot read property 'lists' of undefined"

Guys sorry in advance if my question sounds silly. I am a newbie in reactjs


Solution

  • You need to validate your data, first when the app runs lists is undefined and throws an error. change your render method to the following.

    render() {
    let divstyle = {
      color: "blue",
      fontStyle: "italic",
      fontWeight: "semi-bold"
    };
    
    let toolgroup = this.state.tools.filter(tool => {
      return tool.name === this.state.selectedCategory;
    });
    
    // validate lists and set it to empty array, if toolgroup is empty 
    const lists = toolgroup && toolgroup.length && toolgroup[0].lists || [];
    
    // create select option values
    const items = this.state.tools.map((toolCategory, i) => (
      <option key={i}>{toolCategory.name}</option>
    ));
    
    // create second select option items
    const toolgroupItems = lists.map((list, i) => (
      <option key={i}>{list}</option>
    ));
    
    return (
      <MDBContainer>
        <a
          style={divstyle}
          className="btnadditem"
          title="Add new items"
          onClick={this.toggle}
        >
          <i className="fas fa-plus" />
        </a>
        <MDBModal
          id="modalAdditems"
          isOpen={this.state.modal}
          toggle={this.toggle}
        >
          <MDBModalHeader toggle={this.toggle}>
            Add new Inventory Item
          </MDBModalHeader>
          <MDBModalBody>
            <div className="form-group">
              <label>Description</label>
              <input type="email" className="form-control invModal" />
              <label>Category</label>
              <div>
                <select
                  className="browser-default custom-select"
                  onChange={this.handleChange}
                  value={this.state.selectedCategory}
                >
                  {items}
                </select>
              </div>
              <div>
                <select>
                  {toolgroupItems}
                </select>
    
              </div>
            </div>
          </MDBModalBody>
          <MDBModalFooter>
            <MDBBtn color="secondary" onClick={this.toggle}>
              Close
            </MDBBtn>
            <MDBBtn color="primary" onClick={this.postdata}>
              Save changes
            </MDBBtn>
          </MDBModalFooter>
        </MDBModal>
      </MDBContainer>
     );
    }
    

    working example