title: Populate dependent dropdownboxes in Express using MongoDB
body: <h1>Question</h1>
  <p>How do I create a series (e.g. 2) dropdownboxes that depend on the choice in the previous dropdown box, while both being populated from MongoDB queries from within the Express framework?</p>
  <h1>Example functionality</h1>
  <pre><code> 1. Create a MongoDB database with:
  Volvo
  Audi
  Hyunday
   2. Create a second database with the colors of the cars, e.g.
  Volvo:yellow,red
  Audi:ultra-violet,green
  Hyunday:purple,blue
   3. Show a webpage in localhost that displays a dropdown box with the 3 cars.
   4. When the user selects a car e.g. Volvo, the second dropdownbox should be populated by
  the MongoDB query that returns the colours of that car; e.g. yellow,red.
  
  </code></pre>
  <h1>MWE</h1>
  <p>A complete MWE <a href="https://github.com/a-t-0/PublicCodeLibrary/tree/master/AutomationAndSystems/LearnNodeJS/medium_tutorial/fullstack_app_with_apis" rel="nofollow noreferrer">is found here</a>, you can run it with: <code>npm start</code>.</p>
  <h1>Attempts</h1>
  <p>In response to the comments I have reduced my nr. of listed attempts to a single one. It contains the queries to the MongoDB whose results are displayed on the hosted website as well as a function that removes/renames entries from a dropdownlist.  The attempt is written in file <code>../client/src/app.js</code> and contains:</p>
  <pre><code>// /client/App.js
  import React, { Component } from 'react';
  import axios from 'axios';
  
  class App extends Component {
      
      // initialize our state
      state = {
          data: [],
          id: 0,
          message: null,
          intervalIsSet: false,
          idToDelete: null,
          idToUpdate: null,
          objectToUpdate: null,
      };
      
      // when component mounts, first thing it does is fetch all existing data in our db
      // then we incorporate a polling logic so that we can easily see if our db has
      // changed and implement those changes into our UI
      componentDidMount() {
          this.getDataFromDb();
          if (!this.state.intervalIsSet) {
              let interval = setInterval(this.getDataFromDb, 2000000);
              this.setState({ intervalIsSet: interval });
          }
      }
      
      // never let a process live forever
      // always kill a process everytime we are done using it
      componentWillUnmount() {
          if (this.state.intervalIsSet) {
              clearInterval(this.state.intervalIsSet);
              this.setState({ intervalIsSet: null });
          }
      }
      
      // just a note, here, in the front end, we use the id key of our data object
      // in order to identify which we want to Update or delete.
      // for our back end, we use the object id assigned by MongoDB to modify
      // data base entries
      
      // our first get method that uses our backend api to
      // fetch data from our data base
      getDataFromDb = () =&gt; {
          fetch('http://localhost:3001/api/getData')
                  .then((data) =&gt; data.json())
                  .then((res) =&gt; this.setState({ data: res.data }));
      };
      
      // our put method that uses our backend api
      // to create new query into our data base
      putDataToDB = (message) =&gt; {
          let currentIds = this.state.data.map((data) =&gt; data.id);
          let idToBeAdded = 0;
          while (currentIds.includes(idToBeAdded)) {
              ++idToBeAdded;
          }
          
          axios.post('http://localhost:3001/api/putData', {
              id: idToBeAdded,
              message: message,
          });
      };
      
      // our delete method that uses our backend api
      // to remove existing database information
      deleteFromDB = (idTodelete) =&gt; {
          parseInt(idTodelete);
          let objIdToDelete = null;
          this.state.data.forEach((dat) =&gt; {
              if (dat.id === idTodelete) {
                  objIdToDelete = dat._id;
              }
          });
          
          axios.delete('http://localhost:3001/api/deleteData', {
              data: {
                  id: objIdToDelete,
              },
          });
      };
      
      // our update method that uses our backend api
      // to overwrite existing data base information
      updateDB = (idToUpdate, updateToApply) =&gt; {
          let objIdToUpdate = null;
          parseInt(idToUpdate);
          this.state.data.forEach((dat) =&gt; {
              if (dat.id === idToUpdate) {
                  objIdToUpdate = dat._id;
              }
          });
          
          axios.post('http://localhost:3001/api/updateData', {
              id: objIdToUpdate,
              update: { message: updateToApply },
          });
      };
      
      // option 9:
  //    getOption(){
  //        var select = document.getElementById(&quot;dynamic-select&quot;);
  //        console.log(select);
  //        if(document.getElementById(&quot;dynamic-select&quot;).options.length &gt; 0) {
  //            var option = document.getElementById(&quot;dynamic-select&quot;).options[document.getElementById(&quot;dynamic-select&quot;).selectedIndex];
  //            alert(&quot;Text: &quot; + option.text + &quot;\nValue: &quot; + option.value);
  //        } else {
  //            window.alert(&quot;Select box is empty&quot;);
  //        }
  //    }
      
      addOption(){
          var inputElemAdd = document.getElementsByTagName('select');
          var selectBox = document.getElementById(&quot;dynamic-select&quot;);
          alert(&quot;Current len=&quot;+Object.keys(inputElemAdd));
          alert(&quot;ID props=&quot;+Object.keys(selectBox)); // returns 3 props
          alert(&quot;ID props 2=&quot;+Object.keys(selectBox[2])); // returns 3rd array element (index 2)
          //alert(&quot;ID props 3 error=&quot;+Object.keys(selectBox[3])); // returns 3 props
          alert(&quot;label=&quot;+ selectBox[2].label); // returns 3rd array element (index 2)
          
          selectBox[0].label = &quot;Wrote 0&quot;;
          selectBox[2].label = &quot;Wrote 2&quot;;
          selectBox[3] = new Option('hi, added last label', 'id0',false,false); // add option
      }
      
      removeOption(){
          var inputElem = document.getElementsByTagName('select');
          for(var i = 0; i &lt; inputElem.length; i++) {
                 inputElem[i].options[inputElem[i].selectedIndex] = null; // remove option
          }
      }
  //    
  //    removeAllOptions(){
  //        var select = document.getElementById(&quot;dynamic-select&quot;);
  //        select.options.length = 0;
  //    }
      
      // here is our UI
      // it is easy to understand their functions when you
      // see them render into our screen
      render() {
      const { data } = this.state;
      return (
        &lt;div&gt;
          &lt;ul&gt;
            {data.length &lt;= 0
              ? 'NO DB ENTRIES YET'
              : data.map((dat) =&gt; (
                  &lt;li style={{ padding: '10px' }} key={data.message}&gt;
                    &lt;span style={{ color: 'gray' }}&gt; id: &lt;/span&gt; {dat.id} &lt;br /&gt;
                    &lt;span style={{ color: 'gray' }}&gt; data: &lt;/span&gt;
                    {dat.message}
                  &lt;/li&gt;
                ))}
          &lt;/ul&gt;
          &lt;div style={{ padding: '10px' }}&gt;
            &lt;input
              type=&quot;text&quot;
              onChange={(e) =&gt; this.setState({ message: e.target.value })}
              placeholder=&quot;add something in the database&quot;
              style={{ width: '200px' }}
            /&gt;
            &lt;button onClick={() =&gt; this.putDataToDB(this.state.message)}&gt;
              ADD
            &lt;/button&gt;
          &lt;/div&gt;
          &lt;div style={{ padding: '10px' }}&gt;
            &lt;input
              type=&quot;text&quot;
              style={{ width: '200px' }}
              onChange={(e) =&gt; this.setState({ idToDelete: e.target.value })}
              placeholder=&quot;put id of item to delete here&quot;
            /&gt;
            &lt;button onClick={() =&gt; this.deleteFromDB(this.state.idToDelete)}&gt;
              DELETE
            &lt;/button&gt;
          &lt;/div&gt;
          &lt;div style={{ padding: '10px' }}&gt;
            &lt;input
              type=&quot;text&quot;
              style={{ width: '200px' }}
              onChange={(e) =&gt; this.setState({ idToUpdate: e.target.value })}
              placeholder=&quot;id of item to update here&quot;
            /&gt;
            &lt;input
              type=&quot;text&quot;
              style={{ width: '200px' }}
              onChange={(e) =&gt; this.setState({ updateToApply: e.target.value })}
              placeholder=&quot;put new value of the item here&quot;
            /&gt;
            &lt;button
              onClick={() =&gt;
                this.updateDB(this.state.idToUpdate, this.state.updateToApply)
              }
            &gt;
              UPDATE
            &lt;/button&gt;
            
  
           // Source: https://memorynotfound.com/dynamically-add-remove-options-select-javascript&lt;br&gt;&lt;/br&gt;--&gt;
          &lt;select id=&quot;dynamic-select&quot;&gt;
                  &lt;option value=&quot;1&quot;&gt;one&lt;/option&gt;
                  &lt;option value=&quot;2&quot;&gt;two&lt;/option&gt;
                  &lt;option value=&quot;3&quot;&gt;three&lt;/option&gt;
          &lt;/select&gt;
  
          {/*&lt;button onClick={this.getOption()}&gt;get item&lt;/button&gt;*/}
          &lt;button onClick={this.addOption}&gt;add item&lt;/button&gt; // remove the brackets to make it happen at onclick
          {/*&lt;button type=&quot;button&quot; onClick={this.addOption}&gt;Go&lt;/button&gt;
          &lt;button onClick={this.removeOption()}&gt;remove item&lt;/button&gt;
          &lt;button onClick={this.removeAllOptions}&gt;remove all&lt;/button&gt;*/}
          
          
          &lt;br&gt;&lt;/br&gt;
          {/*//option 10
          // source: https://stackoverflow.com/questions/27834226/add-event-listener-to-collection-of-html-elements*/}
          &lt;input class=&quot;inputs&quot; type=&quot;submit&quot; value=&quot;Hello&quot; /&gt;
          
                  
          &lt;/div&gt;
        &lt;/div&gt;
      );
    }
  }
  
  export default App;
  </code></pre>