My form reset button is not clearing the state of the inputs if I use this.setState({formValues:[]})
in my form reset method. formValues does get reset though by pressing the little x in the input field that appears when setting input property to type="search"
. My inputs are initially set with my input method here:
handleInputChange = (key, value) => {
const newFormValues = Object.assign({}, this.state.formValues, {[key]: value});
this.setState({ formValues: newFormValues })
};
And here is my form reset method..
handleFormReset = () => {
this.setState({formValues:[]})
this.setState({contracts:[]})
}
Also, the data in the input is not being removed from the DOM. If I set the reset button to type="reset"
then the DOM clears, but the state still does not clear.
Here is the search form component..
<form className="form-inline col-md-12" onReset={this.props.handleFormReset}>
{this.props.labels.map(label => (
<div className="card border-0 mx-auto" style={styles} key={label.Id}>
<ul className="list-inline ">
<span>
<li>
<Labels htmlFor={label.DisplayName} >{label.DisplayName}:</Labels>
</li>
<li >
<Input
key={label.Id}
onChange={(event) => {
this.props.handleInputChange(label.DataField, event.target.value)}}
value={(this.props.newFormValues) }
type="text"
maxLength="999"
style={{height:34}}
name="value"
className={"form-control mb-2 mr-sm-2"}
id={label.DataField}
/>
</li>
</span>
</ul>
</div>
))}
<div className=" col-sm-12">
<Button
style={{ float: "left", marginBottom: 10 }}
className="btn btn-success"
type="submit"
onClick={this.props.handleFormSubmit}
>
Search
</Button>
<Help />
<Button
style={{ float: "left", marginBottom: 10 }}
className="btn btn-secondary"
onClick={this.props.clear}
>
Reset
</Button>
</div>
</form>
Here is how the data comes in from the api.. My labels for inputs..
(7) [{…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {Id: 0, DisplayName: "Description", DataValue: "", DataType: "Text", DataField: "IDXT004"}
1: {Id: 1, DisplayName: "Supplier Name", DataValue: "", DataType: "Text", DataField: "IDXT003"}
2: {Id: 2, DisplayName: "Contract #", DataValue: "", DataType: "Number", DataField: "IDXT001"}
3: {Id: 3, DisplayName: "Working Contract ID", DataValue: "", DataType: "Text", DataField: "IDXT002"}
4: {Id: 4, DisplayName: "Sourcing Event", DataValue: "", DataType: "Text", DataField: "IDXT011"}
5: {Id: 5, DisplayName: "Effective Date", DataValue: "", DataType: "Date", DataField: "IDXT005"}
6: {Id: 6, DisplayName: "Expiration Date", DataValue: "", DataType: "Date", DataField: "IDXT006"}
length: 7
My results data api..
(2) [{…}, {…}]
0: {Id: 0, Fields: Array(7), DocImage: {…}}
1: {Id: 1, Fields: Array(7), DocImage: {…}}
length: 2
and further broken down..
0:
DocImage: {sfKey: 6, sfScanIndex: 6, sfFilename: "2222_1.PDF", sfBatchID: 12898, sfFileUnredact: null, …}
Fields: Array(7)
0: {Id: 0, DisplayName: "Description", DataValue: "2018 Summer Camp CEA between the City, NORD and Infinity Educational Advantage, LLC dba IEANOLA", DataType: "Text", DataField: "IDXT004"}
1: {Id: 1, DisplayName: "Supplier Name", DataValue: "Infinity Educational Advantage, LLC", DataType: "Text", DataField: "IDXT003"}
2: {Id: 2, DisplayName: "Contract #", DataValue: "2222", DataType: "Number", DataField: "IDXT001"}
3: {Id: 3, DisplayName: "Working Contract ID", DataValue: "4321", DataType: "Text", DataField: "IDXT002"}
4: {Id: 4, DisplayName: "Sourcing Event", DataValue: "", DataType: "Text", DataField: "IDXT011"}
5: {Id: 5, DisplayName: "Effective Date", DataValue: "03/09/2018", DataType: "Date", DataField: "IDXT005"}
6: {Id: 6, DisplayName: "Expiration Date", DataValue: "03/06/2019", DataType: "Date", DataField: "IDXT006"}
length: 7
You need to set value={this.state.someValue[someProperty]}
on your input element(s).
Setting the object to an empty object doesn't seem to do the trick, as React isn't meant to track deep objects. My workaround for this is to set all the values in your deep object to an empty string.
Finally, I also prefer to use JSON.parse(JSON.stringify(variable))
as it makes true deep copies. Only caveat would be that it doesn't copy references/functions.
Here is a working example with multiple inputs:
let initialState = {
formValues: {}
}
let apiResponse = [
{Id: 0, DisplayName: "Description", DataValue: "", DataType: "Text", DataField: "IDXT004"},
{Id: 1, DisplayName: "Supplier Name", DataValue: "", DataType: "Text", DataField: "IDXT003"},
{Id: 2, DisplayName: "Contract #", DataValue: "", DataType: "Number", DataField: "IDXT001"},
{Id: 3, DisplayName: "Working Contract ID", DataValue: "", DataType: "Text", DataField: "IDXT002"},
{Id: 4, DisplayName: "Sourcing Event", DataValue: "", DataType: "Text", DataField: "IDXT011"},
{Id: 5, DisplayName: "Effective Date", DataValue: "", DataType: "Date", DataField: "IDXT005"},
{Id: 6, DisplayName: "Expiration Date", DataValue: "", DataType: "Date", DataField: "IDXT006"},
]
class App extends React.Component {
constructor(props) {
super(props)
this.state = initialState
}
handleInputChange = (e) => {
let newValues = JSON.parse(JSON.stringify(this.state.formValues))
newValues[e.target.name] = e.target.value
this.setState({
formValues: newValues
})
}
clear = () => {
let emptyValues = JSON.parse(JSON.stringify(this.state.formValues))
Object.keys(emptyValues).forEach(key => emptyValues[key] = "")
this.setState({
formValues: emptyValues
})
}
clearField = (dataField) => {
let newValues = JSON.parse(JSON.stringify(this.state.formValues))
newValues[dataField] = ""
this.setState({
formValues: newValues
})
}
render() {
return (
<div>
<table><tbody>
{
apiResponse.map(res => {
return (<tr key={res.Id}>
<td>{res.DisplayName}</td>
<td><input type={res.DataType}
value={this.state.formValues[res.DataField]}
name={res.DataField}
onChange={this.handleInputChange}/></td>
<td><button onClick={e => this.clearField(res.DataField)}>X</button></td>
<td> State: {this.state.formValues[res.DataField]}</td>
</tr>)
})
}
</tbody></table>
<br/>
<button onClick={this.clear}>Clear</button>
</div>
)
}
}
ReactDOM.render((<App/>), document.getElementById('testing'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="testing">