Monday, 18 November 2019

Populate dependent dropdownboxes in Express using MongoDB

Question

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?

Example functionality

 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.

MWE

A complete MWE is found here, you can run it with: npm start.

Attempts

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 ../client/src/app.js and contains:

// /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 = () => {
        fetch('http://localhost:3001/api/getData')
                .then((data) => data.json())
                .then((res) => this.setState({ data: res.data }));
    };

    // our put method that uses our backend api
    // to create new query into our data base
    putDataToDB = (message) => {
        let currentIds = this.state.data.map((data) => 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) => {
        parseInt(idTodelete);
        let objIdToDelete = null;
        this.state.data.forEach((dat) => {
            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) => {
        let objIdToUpdate = null;
        parseInt(idToUpdate);
        this.state.data.forEach((dat) => {
            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("dynamic-select");
//        console.log(select);
//        if(document.getElementById("dynamic-select").options.length > 0) {
//            var option = document.getElementById("dynamic-select").options[document.getElementById("dynamic-select").selectedIndex];
//            alert("Text: " + option.text + "\nValue: " + option.value);
//        } else {
//            window.alert("Select box is empty");
//        }
//    }

    addOption(){
        var inputElemAdd = document.getElementsByTagName('select');
        var selectBox = document.getElementById("dynamic-select");
        alert("Current len="+Object.keys(inputElemAdd));
        alert("ID props="+Object.keys(selectBox)); // returns 3 props
        alert("ID props 2="+Object.keys(selectBox[2])); // returns 3rd array element (index 2)
        //alert("ID props 3 error="+Object.keys(selectBox[3])); // returns 3 props
        alert("label="+ selectBox[2].label); // returns 3rd array element (index 2)

        selectBox[0].label = "Wrote 0";
        selectBox[2].label = "Wrote 2";
        selectBox[3] = new Option('hi, added last label', 'id0',false,false); // add option
    }

    removeOption(){
        var inputElem = document.getElementsByTagName('select');
        for(var i = 0; i < inputElem.length; i++) {
               inputElem[i].options[inputElem[i].selectedIndex] = null; // remove option
        }
    }
//    
//    removeAllOptions(){
//        var select = document.getElementById("dynamic-select");
//        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 (
      <div>
        <ul>
          {data.length <= 0
            ? 'NO DB ENTRIES YET'
            : data.map((dat) => (
                <li style= key={data.message}>
                  <span style=> id: </span> {dat.id} <br />
                  <span style=> data: </span>
                  {dat.message}
                </li>
              ))}
        </ul>
        <div style=>
          <input
            type="text"
            onChange={(e) => this.setState({ message: e.target.value })}
            placeholder="add something in the database"
            style=
          />
          <button onClick={() => this.putDataToDB(this.state.message)}>
            ADD
          </button>
        </div>
        <div style=>
          <input
            type="text"
            style=
            onChange={(e) => this.setState({ idToDelete: e.target.value })}
            placeholder="put id of item to delete here"
          />
          <button onClick={() => this.deleteFromDB(this.state.idToDelete)}>
            DELETE
          </button>
        </div>
        <div style=>
          <input
            type="text"
            style=
            onChange={(e) => this.setState({ idToUpdate: e.target.value })}
            placeholder="id of item to update here"
          />
          <input
            type="text"
            style=
            onChange={(e) => this.setState({ updateToApply: e.target.value })}
            placeholder="put new value of the item here"
          />
          <button
            onClick={() =>
              this.updateDB(this.state.idToUpdate, this.state.updateToApply)
            }
          >
            UPDATE
          </button>


         // Source: https://memorynotfound.com/dynamically-add-remove-options-select-javascript<br></br>-->
        <select id="dynamic-select">
                <option value="1">one</option>
                <option value="2">two</option>
                <option value="3">three</option>
        </select>

        {/*<button onClick={this.getOption()}>get item</button>*/}
        <button onClick={this.addOption}>add item</button> // remove the brackets to make it happen at onclick
        {/*<button type="button" onClick={this.addOption}>Go</button>
        <button onClick={this.removeOption()}>remove item</button>
        <button onClick={this.removeAllOptions}>remove all</button>*/}


        <br></br>
        {/*//option 10
        // source: https://stackoverflow.com/questions/27834226/add-event-listener-to-collection-of-html-elements*/}
        <input class="inputs" type="submit" value="Hello" />


        </div>
      </div>
    );
  }
}

export default App;


from Populate dependent dropdownboxes in Express using MongoDB

No comments:

Post a Comment