1

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

Dacre Denny
  • 29,664
  • 5
  • 45
  • 65
Samira Arabgol
  • 359
  • 2
  • 5
  • 22

2 Answers2

1

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/lodash@4.17.10/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>
rghossi
  • 563
  • 4
  • 10
0

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>
Dacre Denny
  • 29,664
  • 5
  • 45
  • 65
  • thanks for your answer, I used your logic in the code but when I am trying to console.log(getCustomValidation()) I am getting bunch of true and false before changing any fields. – Samira Arabgol Aug 15 '18 at 14:47
  • Are you sure `getInitialState()` is being called correctly? If so `getCustomValidation()` should return false based on the initial states. This is likely due to `nextProps` passed externally via `componentWillReceiveProps`. Also note that `console.log(getCustomValidation())` is not correct - it should be `console.log(thisgetCustomValidation())` – Dacre Denny Aug 15 '18 at 20:15