【问题标题】:Populate dependent dropdownboxes in Express using MongoDB使用 MongoDB 在 Express 中填充相关下拉框
【发布时间】:2019-11-19 21:33:07
【问题描述】:

问题

如何创建一系列(例如 2 个)下拉框,这些下拉框依赖于上一个下拉框中的选择,同时都从 Express 框架内的 MongoDB 查询中填充?

示例功能

 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

一个完整的 MWE is found here,您可以使用:npm start 运行它。

尝试

为了应对 cme​​ts,我减少了我的 nr。列出的尝试一次。它包含对 MongoDB 的查询,其结果显示在托管网站上,以及从下拉列表中删除/重命名条目的功能。尝试写入文件../client/src/app.js 并包含:

// /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={{ padding: '10px' }} key={data.message}>
                  <span style={{ color: 'gray' }}> id: </span> {dat.id} <br />
                  <span style={{ color: 'gray' }}> data: </span>
                  {dat.message}
                </li>
              ))}
        </ul>
        <div style={{ padding: '10px' }}>
          <input
            type="text"
            onChange={(e) => this.setState({ message: e.target.value })}
            placeholder="add something in the database"
            style={{ width: '200px' }}
          />
          <button onClick={() => this.putDataToDB(this.state.message)}>
            ADD
          </button>
        </div>
        <div style={{ padding: '10px' }}>
          <input
            type="text"
            style={{ width: '200px' }}
            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={{ padding: '10px' }}>
          <input
            type="text"
            style={{ width: '200px' }}
            onChange={(e) => this.setState({ idToUpdate: e.target.value })}
            placeholder="id of item to update here"
          />
          <input
            type="text"
            style={{ width: '200px' }}
            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;

【问题讨论】:

  • 我怀疑是否有人会阅读整个问题。保持简短和简单,只添加解决问题真正需要的代码。
  • @KaleshKaladharan 谢谢你的建议,我删除了后台运行的server.js。
  • 您的反馈很准确,通过简化和结构化/分离我的尝试,并更彻底地尝试一个,我能够删除JSX 格式中的两个错误,函数调用在引号中标记,而它应该在大括号中。这导致了回答该问题所需的关键功能:基于对下拉框的单击来修改 express 框架中的下拉框的能力。我在此功能中包含了简化的 app.js 并删除了其余的尝试。

标签: javascript html node.js mongodb


【解决方案1】:

不确定为什么需要两个不同的数据库,我认为一个数据库中的两个集合更合适,因为在这种情况下,您可以加载聚合所需的所有数据。但是,你如何制定它,你有汽车和颜色的状态,首先隐藏第二个颜色下拉列表,然后在安装时你已经检索汽车。选择汽车后,您请求检索给定汽车的颜色并将其置于状态,然后出现第二个下拉列表。

getCars = async (carId) => {
  try {
    const carsResponse = await fetch(url, { method: 'POST', body: carId });
    const cars = await carsResponse.json();
    this.setState({ cars });
  } catch (err) {
    console.error(err);
  }
}

getColors = () => {
  // pretty same here
}

render () {
  return (
    <ul>
      {this.state.cars.map((car) => {
        return (
           <li key={car.id} onClick={() => this.getColors(car.id)}>car.name</li>
        );
      })}
    </ul>
    {this.state.colors.length > 0 && 
      <ul>
        {this.state.colors.map((color) => {
          <li key={color.id}>color.name</li>
        })}
      </ul>
    }

  );
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-14
    • 1970-01-01
    • 2015-09-09
    • 1970-01-01
    • 2014-03-27
    • 1970-01-01
    相关资源
    最近更新 更多