0

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! :)))

2 Answers 2

1

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>

Sign up to request clarification or add additional context in comments.

Comments

0

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>

    )
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.