Reputation: 3417
I'm rendering a form with an array of data from the database. When I submit the form, handleFormSubmit(event)
, I need to grab all of the input fields. Since I don't know what the input fields are called or how many input fields there will be, how do I access the values?
function CareerPosition(props) {
return (
<li>
<SingleInput
inputType={'text'}
title={'Company name'}
name={'position.company'}
controlFunc={this.handleInputChange}
defaultValue={props.companyName}
placeholder={'Company name'}
bsSize={null}
/>
</li>
)
}
export default class CareerHistoryFormPage extends Component {
constructor(props) {
super(props);
this.state = {
'position.company': '',
'position.title': '',
profileCandidateCollectionId: null,
errors: {}
};
this.handleFormSubmit = this.handleFormSubmit.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
renderCareerPositions(props) {
const profileCandidateCollection = this.props.profileCandidate;
const careerHistoryPositions = profileCandidateCollection && profileCandidateCollection.careerHistoryPositions;
if(careerHistoryPositions) {
const careerPositions = careerHistoryPositions.map((position) =>
<CareerPosition
key={position.uniqueId}
companyName={position.company}
positionTitle={position.title}
uniqueId={position.uniqueId}
/>
);
return (
<ul>
{careerPositions}
</ul>
)
}
}
handleFormSubmit(event) {
event.preventDefault();
console.log("AllFormData:", this.state.value);
}
render() {
return (
<Row className="show-grid">
<Col sm={12} md={3}>
<EditCandidateProfileLinks />
</Col>
<Col sm={12} md={9}>
<div className="paper">
<form className="careerHistoryForm" onSubmit={this.handleFormSubmit}>
<section className="form-title">
<h3 className="text-center">Career History</h3>
</section>
<hr />
<section className="form-content">
{this.state.errors.databaseError ? <AlertNotification bsStyle="danger" error={this.state.errors.databaseError} /> : '' }
{this.renderCareerPositions()}
<SingleInput
inputType={'text'}
title={'Company name'}
name={'position.company'}
controlFunc={this.handleInputChange}
content={this.state['position.company']}
placeholder={'Company name'}
bsSize={null}
error={this.state.errors['position.company']}
/>
<SingleInput
inputType={'text'}
title={'Title'}
name={'position.title'}
controlFunc={this.handleInputChange}
content={this.state['position.title']}
placeholder={'Title'}
bsSize={null}
error={this.state.errors['position.title']}
/>
</section>
<hr />
<section className="form-buttons">
<input type="submit" className="btn btn-primary" value="Save" />
</section>
</form>
</div>
</Col>
</Row>
);
}
}
CareerHistoryFormPage.propTypes = {
profileCandidate: PropTypes.object
};
Upvotes: 0
Views: 55
Reputation: 22322
I think we can make it work using some minor changes.
As you have stated data is located in your state as following:
this.state = {
'position.company': '',
'position.title': '',
/*... There are some "service" accommodating data...*/
profileCandidateCollectionId: null,
errors: {}
};
And you have no control over amount of its properties as it is fetched from DB. Lets refactor it a bit and put all dynamic data in its own object inside state, like this:
this.state = {
data: {
'position.company': '',
'position.title': ''
}
/*... There are some "service" accommodating data...*/
profileCandidateCollectionId: null,
errors: {}
};
Now in your render method we can safely iterate over all properties of the "data" and render one input per each (without need for hardcoding this):
render()
{
var inputs = [];
for(var pName of Object.keys(this.state.data))
{
inputs.push(
<SingleInput
inputType={'text'}
title={'Title'}
name={pName}
controlFunc={this.handleInputChange}
content={this.state.data[pName]}
placeholder={'Title'}
bsSize={null}
error={this.state.errors[pName]}
/>
);
}
}
Note I omit how placeholder should be handled - you can do this in the similar manner.
And handleInputChange
will look somewhat similar to:
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
var data = {...this.state.data, ...{[name]: value}};
this.setState({
data: data
});
}
Now after any change of the input - your state.data
will always contain updated data - so there is no need to collect it explicitly.
Upvotes: 1