Dorinaaaa
Dorinaaaa

Reputation: 1

Disable a button when the input fields are empty in reactjs

Im new to reactJS. Im wondering why my code below doesnt work. Everything works except disabling my NEXT button when text fields are empty. My expectation is that after i fill out ALL the textboxes, the NEXT button will be enabled.

class Registration extends React.Component {
constructor (props) {
    super (props);
    this.state = {
        selectedGender: null,
        errors: [],
        initComplete: false
    }

    this._handleSubmit = this._handleSubmit.bind(this);
    this._handleInputMobileOnChange = 
    this._handleInputMobileOnChange.bind(this);
    this.clearError = this.clearError.bind(this);
}
clearError () {
    this.setState({ errors: [] });
}

_handleInputMobileOnChange (e) {
    e.preventDefault();
    this.clearError();
    e.target.value = utils.removeNonNumbers(e.target.value);
    //this.setState({value: e.target.value})
}

change(e){
    if("" != e.target.value){
        this.button.disabled = false;
    }
    else{
        this.button.disabled = true;
    }
}
render() {
    return (
            <div className="container-fluid">
                <form onSubmit={this._handleSubmit}>
                    <div className="form-group has-danger">
                        <label htmlFor="input-MobileNum">number *</label>
                        <input ref={(ref) => this.inputMobile = ref} type="tel" className={'form-control ' } id="input-MobileNum" onChange={()=>{ this._handleInputMobileOnChange; this.change.bind(this)}} defaultValue=""/>
                    </div>
                    <div className="form-group has-danger">
                        <label htmlFor="input-Email">Email address *</label>
                        <input ref={(ref) => this.inputEmail = ref} type="email" className={'form-control '} id="input-Email" defaultValue="" onChange={()=>{ this.clearError; this.change.bind(this)}}/>
                    </div>
                    <div className="form-group has-danger">
                        <label htmlFor="input-Invitation">Invitation code</label>
                        <input ref={(ref) => this.inputInvitation = ref} type="text" className={'form-control '} id="input-Invitation" defaultValue="" onChange={()=>{ this.clearError; this.change.bind(this)}}/>
                    </div>
                    <div className="form-group cta">
       //NEXT BUTTON
                        <button type="submit" className="btn btn-primary" ref={(button) => this.button=button}>Next</button>
                    </div>
                </form>
            </div>

    )
}

THANKS!!!

I updated my code to this. And i tested it case by case. Only mobile works, the email and invitation code dont work for some reason.

class Registration extends React.Component {
    constructor (props) {
        super (props);
        this.state = {
            selectedGender: null,
            errors: [],
            initComplete: false
        }

    this._handleSubmit = this._handleSubmit.bind(this);
    this._handleInputMobileOnChange = 
    this._handleInputMobileOnChange.bind(this);
    this._handleInputEmailOnChange = 
    this._handleInputEmailOnChange.bind(this);
    this._handleInputInvitationOnChange = 
    this._handleInputInvitationOnChange.bind(this);
    this.clearError = this.clearError.bind(this);
}
clearError () {
    this.setState({ errors: [] });
}

disable(){
    let disable = true;
    if (this.state.inputMobile || this.state.inputEmail || this.state.inputInvitation) {     //I tried && operator, still only mobile works
        disable = false;
    } 
    return disable;
}

_handleInputMobileOnChange (e) {
    e.preventDefault();
    this.clearError();
    e.target.value = utils.removeNonNumbers(e.target.value);
    this.setState({inputMobile: e.target.value})
}

_handleInputEmailOnChange(e){
    e.preventDefault();
    this.clearError();
    e.target.value = utils.removeNonNumbers(e.target.value);
    this.setState({inputEmail: e.target.value})
}

_handleInputInvitationOnChange(e){
    e.preventDefault();
    this.clearError();
    e.target.value = utils.removeNonNumbers(e.target.value);
    this.setState({inputInvitation: e.target.value})
}

change(e){
    if("" != e.target.value){
        this.button.disabled = false;
    }
    else{
        this.button.disabled = true;
    }
}
render() {
    return (
            <div className="container-fluid">
                <form onSubmit={this._handleSubmit}>
                    <div className="form-group has-danger">
                        <label htmlFor="input-MobileNum">number *</label>
                        <input ref={(ref) => this.inputMobile = ref} type="tel" className={'form-control ' } id="input-MobileNum" onChange={this._handleInputMobileOnChange}} defaultValue=""/>
                    </div>
                    <div className="form-group has-danger">
                        <label htmlFor="input-Email">Email address *</label>
                        <input ref={(ref) => this.inputEmail = ref} type="email" className={'form-control '} id="input-Email" defaultValue="" onChange={this._handleInputEmailOnChange}/>
                    </div>
                    <div className="form-group has-danger">
                        <label htmlFor="input-Invitation">Invitation code</label>
                        <input ref={(ref) => this.inputInvitation = ref} type="text" className={'form-control '} id="input-Invitation" defaultValue="" onChange={this._handleInputInvitationOnChange}/>
                    </div>
                    <div className="form-group cta">
       //NEXT BUTTON
                        <button type="submit" className="btn btn-primary" disabled={this.disable()}>Next</button>
                    </div>
                </form>
            </div>

    )
}

Nvm. I was being stupid. The code above works! :)))

Upvotes: 0

Views: 4393

Answers (2)

Chris
Chris

Reputation: 59551

You should consider using controlled input elements rather than uncontrolled. This lets react manage the values of your input elements which makes things a bit easier.

First of all start by adding the initial values of each input element to to your constructor. You probably just want empty strings here ("").

Then, add a change event listener for each input element and create a function for each. Each such function should then check what the value for the other elements are, as well as its own, and then enable or disable the button.


Demo:

class Registration extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
        selectedGender: null,
        errors: [],
        initComplete: false,
        buttonIsDisabled: true,
        numberValue: "",
        emailValue: "",
        codeValue: "",
    }
    this.changeNumber = this.changeNumber.bind(this);
    this.changeEmail = this.changeEmail.bind(this)
    this.changeCode = this.changeCode.bind(this);
  }
  
  changeNumber = (e) => {
    let s = true;
    if(this.state.emailValue.length && this.state.codeValue.length && e.target.value.length) {
      s = false;
    }
    let val = e.target.value;
    //let val = utils.removeNonNumbers(e.target.value);
    this.setState({numberValue: val, buttonIsDisabled: s, errors: []});
  }
  
  changeEmail = (e) => {
    let s = true;
    if(this.state.numberValue.length && this.state.codeValue.length && e.target.value.length) {
      s = false;
    }
    this.setState({emailValue: e.target.value, buttonIsDisabled: s, errors: []});
  }
  
  changeCode = (e) => {
    let s = true;
    if(this.state.numberValue.length && this.state.emailValue.length && e.target.value.length) {
      s = false;
    }
    this.setState({codeValue: e.target.value, buttonIsDisabled: s, errors: []});
  }
  
  render() {
    return (
            <div className="container-fluid">
                <form onSubmit={this._handleSubmit}>
                    <div className="form-group has-danger">
                        <label htmlFor="input-MobileNum">number *</label>
                        <input type="tel" className={'form-control ' } id="input-MobileNum" onChange={this.changeNumber} />
                    </div>
                    <div className="form-group has-danger">
                        <label htmlFor="input-Email">Email address *</label>
                        <input type="email" className={'form-control '} id="input-Email" onChange={this.changeEmail} />
                    </div>
                    <div className="form-group has-danger">
                        <label htmlFor="input-Invitation">Invitation code</label>
                        <input type="text" className={'form-control '} id="input-Invitation" onChange={this.changeCode} />
                    </div>
                    <div className="form-group cta">
                        <button type="submit" className="btn btn-primary" disabled={this.state.buttonIsDisabled} ref={(button) => this.button=button}>Next</button>
                    </div>
                </form>
            </div>

    )
}}

ReactDOM.render(<Registration />, document.getElementById("myApp"));
<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="myApp"></div>

Upvotes: 1

Shubham Khatri
Shubham Khatri

Reputation: 282160

Keep a state disabled and then on change function check whether all inputs have value , then set the state disabled to false like below snippet

class Registration extends React.Component {
constructor (props) {
    super (props);
    this.state = {
        selectedGender: null,
        errors: [],
        initComplete: false, 
        disabled: true
    }

    this._handleSubmit = this._handleSubmit.bind(this);
    this._handleInputMobileOnChange = 
    this._handleInputMobileOnChange.bind(this);
    this.clearError = this.clearError.bind(this);
}
clearError () {
    this.setState({ errors: [] });
}

_handleInputMobileOnChange (e) {
    e.preventDefault();
    this.clearError();
    e.target.value = utils.removeNonNumbers(e.target.value);
    //this.setState({value: e.target.value})
}

change = () => {
    if(this.inputMobile !== '' && this.inputEmail !== '' && this.inputInvitation != '' ) {
         this.setState({disabled: false});
    }
}
render() {
    return (
            <div className="container-fluid">
                <form onSubmit={this._handleSubmit}>
                    <div className="form-group has-danger">
                        <label htmlFor="input-MobileNum">number *</label>
                        <input ref={(ref) => this.inputMobile = ref} type="tel" className={'form-control ' } id="input-MobileNum" onChange={()=>{ this._handleInputMobileOnChange; this.change.bind(this)}} defaultValue=""/>
                    </div>
                    <div className="form-group has-danger">
                        <label htmlFor="input-Email">Email address *</label>
                        <input ref={(ref) => this.inputEmail = ref} type="email" className={'form-control '} id="input-Email" defaultValue="" onChange={()=>{ this.clearError; this.change.bind(this)}}/>
                    </div>
                    <div className="form-group has-danger">
                        <label htmlFor="input-Invitation">Invitation code</label>
                        <input ref={(ref) => this.inputInvitation = ref} type="text" className={'form-control '} id="input-Invitation" defaultValue="" onChange={()=>{ this.clearError; this.change.bind(this)}}/>
                    </div>
                    <div className="form-group cta">
       //NEXT BUTTON
                        <button type="submit" className="btn btn-primary" ref={(button) => this.button=button} disabled={this.state.disabled}>Next</button>
                    </div>
                </form>
            </div>

    )
}

Upvotes: 0

Related Questions