Reputation: 389
I have a form which has a large number of inputs and update button. I am looking for the best way to disable the button unless one of the states or inputs get changed. I know about the way that having Boolean state variable to hold the button's disable/enable state. Then on change of the input field set value to the state variable name accordingly.
since i have a large number of states. I need to write a code which loop trough the nested object and compare.
I would appreciate your help
Upvotes: 1
Views: 3022
Reputation: 598
I don't see why the boolean
approach would be bad.
Anyways, you could compare your previous model object with your current state using lodash _.isEqual function to check whether data has changed or not.
UPDATE (snippet):
class App extends React.Component {
state = {
foo: '',
bar: ''
}
componentDidMount() {
const { foo, bar } = this.props;
this.setState({ foo, bar });
}
hasChangedSinceInitialState = () => {
const { foo, bar } = this.props;
// here you could use lodash ._isEqual if you have an bigger object
return (foo === this.state.foo && bar === this.state.bar);
}
handleInputChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
}
render() {
return (<div>
<div>Foo: <input type='text' name='foo' value={this.state.foo} onChange={this.handleInputChange} /></div>
<div>Bar: <input type='text' name='bar' value={this.state.bar} onChange={this.handleInputChange} /></div>
<button disabled={this.hasChangedSinceInitialState()}>Submit</button>
</div>);
}
}
ReactDOM.render(<App foo='oldFoo' bar='oldBar' />, document.getElementById('root'));
<script src="https://cdn.jsdelivr.net/npm/[email protected]/isEqual.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='root'></div>
Upvotes: 1
Reputation: 30390
If I understand your situation and code correctly, then you are only interested in validating on certian variables in your component state.
You could achieve the desired validation behaviour by adding the following method to your component:
getCustomValidation() {
// Extract a list for validation on only the state fields that are
// relevance to the form validation
const fieldsToValidate = [
"ppvLimit",
"securityCode",
"primaryPhone",
"secondaryPhone",
"email",
"billingAddressLine1",
"billingAddressLine2",
"billingAddressCity",
"billingAddressTerritoryCode",
"billingAddressPostalCode",
"contactAddressLine1",
"contactAddressLine2",
"contactAddressCity",
"contactAddressTerritoryCode",
"contactAddressPostalCode",
"authorizedUser1",
"authorizedUser2",
"authorizedUser3",
"authorizedUser4"
];
// Iterate each field to check to determine if field is valid
for(const fieldToValidate of fieldsToValidate) {
// Extract value for current field
const value = this.state[ fieldToValidate ]
// If value is "truthy" then return valid (true)
if( !!value ) {
return true
}
}
// If none of the validation fields are valid, return false
return false;
}
To make use of this, you could update the Submit component in your render method as follows:
<Button primary disabled={ !this.getCustomValidation() } type="submit">
{ loading ? <div><LoadingIcon size="lg" /> Saving...</div> : "Update" }
</Button>
Upvotes: 0