reactjs - React - 如何生成动态表单
问题描述
我有一种形式,我需要为联系人对象添加动态详细信息。我需要将以下格式的数据发送到 API
有效载荷:
{
name: "The org name",
detail: "The org detail",
attributes: {
address: {
lines: [],
city: "",
state: "",
country: "India",
zip: ""
},
contacts: [
{
name: "abc",
phone: "PH"
},
{
name: "x",
phone: "PH"
}
]
}
};
一切都完成了,但我不知道如何动态设置联系人表单。下面是我的表单代码
export default class OrganizationForm extends Component {
state = {
loading: this.props.match.params.id ? true : false,
organizationForm: {
name: "",
detail: "",
type: "org",
attributes: {
contacts: [{
name: '',
phone: ''
}],
address: {
lines: [],
city: "",
state: "",
country: "",
zip: ""
}
}
},
errors: {}
};
componentDidMount() {
const { match } = this.props;
if (match.params.id) {
OrganizationService.getOrganization(match.params.id)
.then(response => {
if (response.status === 200) {
this.setState({
organizationForm: { ...response.data },
loading: false
});
}
})
.catch(function(error) {
// catch this error on state and show user regarding error
console.log(error.response);
});
}
}
handleChange = change => {
const newState = {
organizationForm: {
...this.state.organizationForm,
...change
}
};
this.setState(newState);
};
handleSubmit(e) {
e.preventDefault();
var id = currentLoggedInUser().belongs.id;
var callCategoryApi = () => {};
const { match } = this.props;
const data = { ...this.state.organizationForm };
// make this contacts part of handle change and then remove it.
data.attributes.contacts = [];
if (!match.params.id) {
callCategoryApi = OrganizationService.createOrganizations(data, id);
} else {
callCategoryApi = OrganizationService.editOrganizations(
data,
match.params.id
);
}
callCategoryApi
.then(response => {
if (response.status === 200) {
this.props.history.goBack();
}
})
.catch(error => {
console.log(error.response);
});
}
render() {
const { organizationForm, loading } = this.state;
const { match } = this.props;
if (loading) {
// replace this loading as per design
return <h3 style={{ marginTop: "30px" }}>Loading...</h3>;
}
return (
<div className="welcome-wrap">
<br />
<h3 className="text-center">
{match.params.id ? "Edit Organization" : "Add Organization"}
</h3>
<hr />
<Col className="create-content-wrap" sm={12}>
<form className="">
<FormGroup className="custom-form-group required row">
<ControlLabel className="custom-form-control-label col-sm-3">
Name
</ControlLabel>
<FormControl
className="custom-form-control col-sm-9"
type="text"
name="name"
value={organizationForm.name}
onChange={event => {
this.handleChange({ name: event.target.value });
}}
/>
</FormGroup>
<FormGroup className="custom-form-group required row">
<ControlLabel className="custom-form-control-label col-sm-3">
Detail
</ControlLabel>
<FormControl
className="custom-form-control col-sm-9"
type="text"
name="detail"
componentClass="textarea"
value={organizationForm.detail}
onChange={event => {
this.handleChange({ detail: event.target.value });
}}
/>
</FormGroup>
<FormGroup className="custom-form-group row">
<ControlLabel className="custom-form-control-label col-sm-3">
Address
</ControlLabel>
<FormControl
className="custom-form-control col-sm-9"
type="text"
name="lines"
componentClass="textarea"
value={organizationForm.attributes.address.lines.join("\n")}
onChange={event => {
this.handleChange({
attributes: {
address: {
...organizationForm.attributes.address,
lines: event.target.value.split("\n")
}
}
});
}}
/>
</FormGroup>
<FormGroup className="custom-form-group row">
<ControlLabel className="custom-form-control-label col-sm-3">
City
</ControlLabel>
<FormControl
className="custom-form-control col-sm-9"
type="text"
name="city"
value={organizationForm.attributes.address.city}
onChange={event => {
this.handleChange({
attributes: {
address: {
...organizationForm.attributes.address,
city: event.target.value
}
}
});
}}
/>
</FormGroup>
<FormGroup className="custom-form-group row">
<ControlLabel className="custom-form-control-label col-sm-3">
State
</ControlLabel>
<FormControl
className="custom-form-control col-sm-9"
type="text"
name="state"
value={organizationForm.attributes.address.state}
onChange={event => {
this.handleChange({
attributes: {
address: {
...organizationForm.attributes.address,
state: event.target.value
}
}
});
}}
/>
</FormGroup>
<FormGroup className="custom-form-group row">
<ControlLabel className="custom-form-control-label col-sm-3">
Country
</ControlLabel>
<FormControl
className="custom-form-control col-sm-9"
type="text"
name="country"
value={organizationForm.attributes.address.country}
onChange={event => {
this.handleChange({
attributes: {
address: {
...organizationForm.attributes.address,
country: event.target.value
}
}
});
}}
/>
</FormGroup>
<FormGroup className="custom-form-group row">
<ControlLabel className="custom-form-control-label col-sm-3">
Zipcode
</ControlLabel>
<FormControl
className="custom-form-control col-sm-9"
type="number"
name="zip"
value={organizationForm.attributes.address.zip}
onChange={event => {
this.handleChange({
attributes: {
address: {
...organizationForm.attributes.address,
zip: event.target.value
}
}
});
}}
/>
</FormGroup>
<FormGroup className="custom-form-group row">
<ControlLabel className="custom-form-control-label col-sm-3">
Contacts
</ControlLabel>
<FormControl
className="custom-form-control col-sm-9"
type="number"
name="contacts"
// value={organizationForm.attributes.contacts}
// onChange={this.handleChange.bind(this)}
/>
</FormGroup>
</form>
</Col>
<div className="">
<Link to="/stw/setting/organization" className="btn btn-secondary">
Cancel
</Link>
<button
type="submit"
className="btn btn-primary ml-2"
onClick={event => this.handleSubmit(event)}
>
Save
</button>
</div>
</div>
);
}
}
应该有一个添加联系人和删除联系人按钮,单击该按钮,我应该从表单中添加或删除联系人。
如何从我的表单创建动态联系人数组?
更新 表单现在如下所示,当我单击添加联系人时,它应该再添加 2 个姓名和电话文本框,并且添加联系人按钮应该位于该 2 个文本框下方。
解决方案
在您的州名为 currentContact 的 store 和附加选项,如下所示:
state= {
currentContact: {name: '', phone: ''},
showContactForm: false,
organizationForm: {...}
}
那么你可以这样做:
<FormGroup className="custom-form-group row">
<ControlLabel className="custom-form-control-label col-sm-3">
Contacts
</ControlLabel>
<button onClick={this.showContactForm}>add contact</button>
{this.state.showContactForm &&
<FormGroup className="custom-form-group row">
<ControlLabel className="custom-form-control-label col-sm-3">
name
</ControlLabel>
<FormControl
className="custom-form-control col-sm-9"
type="text"
name="name"
onChange={this.handleNameChange}
/>
<ControlLabel className="custom-form-control-label col-sm-3">
phone
</ControlLabel>
<FormControl
className="custom-form-control col-sm-9"
type="text"
name="phone"
onChange={this.handlePhoneChange}
/>
</FormGroup>
}
{this.state.organizationForm.attributes.contacts.map((contact,index)=>{
return <div>{contact.name}<button onClick={()=>{this.removeContact(index)}}>remove</button></div>
})}
</FormGroup>
组件中的 removeContact 函数应该是:
removeContact = (index)=>{
const {contacts} = this.state.organizationForm.attributes;
contacts.splice(index,1);
this.handleChange({attributes: {contacts});
}
addContact 函数:
showContactForm = (e)=>{
e.preventDefault();
if(!this.state.showContactForm){
this.setState({showContactForm: true});
} else {
this.addContact(e)
}
}
addContact = (e)=>{
e..preventDefault();
const {name, phone} = this.state.currentContact;
const {contacts} = this.state.organizationForm.attributes;
contacts.push(this.state.currentContact);
this.handleChange({attributes: {...this.state.organizationForm.attributes, contacts}});
}
handleNameChange 和 handlePhoneChange 函数:
handleNameChange = (e)=>{
this.setState({currentContact: {...this.state.currentContact, name:
e.target.value}})
}
handlePhoneChange = (e)=>{
this.setState({currentContact: {...this.state.currentContact, phone:
e.target.value}})
}
推荐阅读
- apache - 如何在詹金斯中一次性为多个工作添加特定的后期构建动作?
- android - Fresco 从文件中播放 gif
- java - Java 给我一个错误“java.io.ioexception 永远不会被抛出相应的 try 语句的主体”
- multithreading - 即席多线程和 Spark
- asp-classic - 选择 xml 节点无法选择特定数据
- gpx - 导出地图行程以将其用于(TomTom)等设备
- apache-camel - Camel 中批量消费者的聚合结果(例如来自 SQS)
- vue.js - [Vue 警告]:属性或方法“索引”未在实例上定义,但在渲染期间引用
- elasticsearch - 映射搜索分析器(带撇号)不起作用
- c# - 我在微软的逆变示例中遗漏了什么?