【发布时间】:2018-11-13 09:37:44
【问题描述】:
问题
大家好,谁能帮我解决这个复杂的问题? : 我正在使用 Spring boot v2.0.5 和 React.js v15.6.2、ReactDom v15.6.2、React Bootstrap v0.32.4 创建一个应用程序,并且我的前端和服务器端部分之间的链接是由使用 Spring 注释的 restful web 服务组成的后面和前面的 fetch API。我的 React 组件是按照父子设计模式概念制作的,这意味着:我的一些组件可以是其他一些组件的子级,反之亦然。
它是如何工作的?
我有一个包含列和行的表格,表格中的每一行都有一个唯一的 ID、2 个下拉菜单、1 个文本输入、2 个日期选择器和 1 个文件上传输入,这是导致主要问题的原因;用户可以通过单击“+文档”按钮添加更多与之前具有相同组件的行;每行都有一个唯一的增量Id,类型为number(整数);下拉菜单和输入事件由父组件内的一种方法根据它们的标签名称处理; 我将用户输入的所有数据存储在对象({})的列表([])中。
示例:如果用户只填写第一行;存储在列表状态中的对象将是这样的:
[{id:0,type:"forms",lang:"all",libelle:"some strings",dateBegin:"11-12-2018",dateEnd:"12-12-2018",document:{File(154845)}]
如果用户添加另一行,然后像第一行一样填充它,列表将是这样的:
[{id:0,type:"forms",lang:"all",libelle:"some strings",dateBegin:"11-12-2018",dateEnd:"12-12-2018",document:{File(154845)},{id:1,type:"howTo",lang:"en",libelle:"some strings",dateBegin:"11-12-2018",dateEnd:"01-01-2019",document:{File(742015)}]
查看此图片以了解表格的外观: Table Demo
Presentational 组件类(主组件的子级)中的表作为代码
class Presentational extends React.Component {
constructor(props) {
super(props);
this.state = {
docObjList: [],
element: (
<FormDocRowItem // this contains the table tbody tds elements..
id={1}
handleChanges={this.props.handleChanges}/>)
};
this.handleAddDocumentRow = this.handleAddDocumentRow.bind(this);
}
// handleAddDocumentRow method
handleAddDocumentRow(e) {
const value = e.target.value;
const name = e.target.name;
if (name === 'add') {
let arr = this.state.docObjList; // get the list state
// assign the new row component
arr = [...arr, Object.assign({}, this.state.element)];
// set the new list state
this.setState({docObjList: arr});
}
// if name === 'delete' logic..
}
// render method
render() {
const {handleReset} = this.props;
return(
<FormGroup>
<Form encType="multipart/form-data">
<Table striped bordered condensed hover>
<thead>
<tr>
<th>id</th>
<th>Type</th>
<th>Lang</th>
<th>Title</th>
<th>Date begin</th>
<th>Date end</th>
<th>+ Document</th>
<th>Options</th>
</tr>
</thead>
<tbody>
{this.state.element} // this row is required as initialization
{
this.state.docObjList.map((doc, index) => {
// as index in map() starts from 0 and there is an
// already row component above => The index inside the
// table should start from 1 except The key property
// which should know the right index of the function
const id = index+1;
return (
<tr key={index}>
<td>
{id}
</td>
<td>
<DocumentTypes id={id} handleChange={this.props.handleChanges}/>
</td>
<td>
<DocumentLanguage id={id} handleChange={this.props.handleChanges}/>
</td>
<td>
<DocumentLibelle id={id} handleChange={this.props.handleChanges}/>
</td>
<td>
<FormControl id={''+id} name="dateBegin" componentClass="input" type="date"
onChange={this.props.handleChanges}/>
</td>
<td>
<FormControl id={''+id} name="dateEnd" componentClass="input" type="date"
onChange={this.props.handleChanges}/>
</td>
<td>
<Document id={id} handleChange={this.props.handleChanges}/>
</td>
{
this.state.docObjList.length == index + 1 &&
<td>
<button type="button" style={{verticalAlign: 'middle', textAlign: 'center'}} id={index + 1}
name="delete"
onClick={this.handleAddDocumentRow}>
Delete
</button>
</td>
}
</tr>
);
})
}
</tbody>
</Table>
<button type="button" name="add" onClick={this.handleAddDocumentRow}>+ Document</button>
<FormGroup>
<Button type="reset"
style={{marginRight: '20%'}}
className="btn-primary"
onClick={this.props.handleClickSubmit}>Submit</Button>
<Button name="back" onClick={this.props.handleClickSubmit}>Annuler</Button>
</FormGroup>
</Form>
</FormGroup>
)
}
}
行组件类(Presentational的子组件)
const FormDocRowItem = (props) => {
const {id} = props; // the ID here is refering the column that is going to be
// show inside the table not the index of the map function
return(
return (
<tr>
<td>
{id}
</td>
<td>
<DocumentTypes id={id} handleChange={this.props.handleChanges}/>
</td>
<td>
<DocumentLanguage id={id} handleChange={this.props.handleChanges}/>
</td>
<td>
<DocumentLibelle id={id} handleChange={this.props.handleChanges}/>
</td>
<td>
<FormControl id={''+id} name="dateBegin" componentClass="input" type="date" onChange={this.props.handleChanges}/>
</td>
<td>
<FormControl id={''+id} name="dateEnd" componentClass="input" type="date" onChange={this.props.handleChanges}/>
</td>
<td>
<Document id={id} handleChange={this.props.handleChanges}/>
</td>
</tr>
);
}
}
父组件类(主组件)
constructor(props) {
this.state ={
docDataList: [],
formIsReadyToSubmit: false
}
this.handleSubmit = this.handleSubmit.bind(this); // button submit click
this.handleReset = this.handleReset.bind(this); // button reset click
this.fillWithData = this.fillWithData.bind(this); // handle changes
}
// handleReset method..
fillWithData(e) {
const name = e.target.name; // get the name of the target
const id = parseInt(e.target.id); // get the id of the target
let value = e.target.value; // get the value of the target
let arr = this.state.docDataList; // get the list state
// if the target is a file upload
if (name === 'selectDocument')
value = e.target.files[0];
// create properties with null values starting from the first onchange
// event handling, to not get a misplaced properties inside the
// objects of the list state
arr.map((x) => {
x.type = x.type ? x.type : null;
x.lang = x.lang ? x.lang : null;
x.libelle = x.libelle ? x.libelle : null;
x.dateBegin = x.dateBegin ? x.dateBegin : null;
x.dateEnd = x.dateEnd ? x.dateEnd : null;
x.document = x.document ? x.document : null;
});
// if the event target name is not delete
if (name != 'delete') {
// check if the object id already exist in the table
// if it exists, the new value should replace the previous one
// and not allowed to add a new object to the list state
if ((arr.find((x) => x.id == id))) {
// loop through the list state to find the id of the object
arr.map((x) => {
if (x.id == id) {
// helper variable to prevent empty strings
const val = value != '' ? value : null;
switch (name) {
case 'selectType':
x.type = val;
break;
case 'selectLang':
x.lang = val;
break;
case 'libelle':
x.libelle = val;
break;
case 'dateBegin':
x.dateBegin = val;
break;
case 'dateEnd':
x.dateEnd = val;
break;
case 'selectDocument':
x.document = val;
break;
}
}
});
// assign the new list to my docDataList state
// mentioning that the id of the element already exist
this.setState({docDataList: arr}, () => {
console.log(' ID exist; new dataList :', this.state.docDataList);
});
}
// if the id doesn't exist (means that the button +document is clicked)
else {
// again, a helper variable as the previous statement
const val = value != '' ? value : null;
this.setState({
docDataList: [...arr, Object.assign({
id: id,
type: name === 'selectType' ? val : null,
lang: name === 'selectLang' ? val : null,
libelle: name === 'libelle' ? val : null,
dateBegin: name === 'dataBegin' ? val : null,
dateEnd: name === 'dateEnd' ? val : null//,
//document: name==='selectDocument'? val:null
})]
}, () => {
console.log('ID doesnt exist; new dataList :', this.state.docDataList);
});
}
}
}
HandleSubmit() 方法(在父组件类中)
// Submit button click handler
handleSubmit(e) {
let docDataList = this.state.docDataList;
// if the user didn't touch any thing on the table rows
// that means the list is empty and its length = 0
if (docDataList.length === 0) {
this.setState({
alerts: {
message: 'Please enter your document information ',
show: true
}
});
}
// if the user has entered a data on the table row
else if (docDataList.length > 0) {
let data = new FormData(); // object which will be sent
// check the docDataList before request
console.log('DocDataList before request:', docDataList);
data.append('docDataList', JSON.stringify(docDataList));
fetch('http://localhost:8080/api/files/uploadFile', {
method: 'POST',
body: data
}).then(response => {
console.log('success document upload', response);
}).catch(error => {
console.log('error', error);
});
this.setState({
formIsReadyToSubmit: true,
docDataList: [], // reset the list
alerts: {updateAlert: true} // make an alert
});
}
}
查看当我用数据填充行时控制台显示的内容:CLICK HERE PLEASE
查看请求的响应:CLICK HERE PLEASE
注意:观看这些屏幕截图后,您可能会注意到,有一个额外的数据列表称为“arrContrats”,我没有在我的问题中提及它,因为它没有任何问题;问题在于“docDataList”列表。提前致谢
【问题讨论】:
-
请阅读:minimal reproducible example。上面有far太多不相关的信息。此外,请不要使用随机格式(块引号、粗体等)。只需简单、清晰、简洁地提出您的问题。更多:How do I ask a good question?
-
我已经删除了很多代码以使其尽可能简单,但感谢您的建议
-
恕我直言,我们不需要上述的 80%。再次,请修复格式。如果您不引用,请不要使用引用标记。 ALL CAPS 大喊大叫,这对获得人们的帮助会适得其反。不必要的黑体字只会使您的问题更难阅读,如果目标是寻求帮助,这又会适得其反。
-
我只是用引号来突出一些细节
-
好吧,我照你说的做了
标签: json reactjs spring-boot fetch-api react-bootstrap