【发布时间】: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 运行它。
尝试
为了应对 cmets,我减少了我的 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