0

I created a Contact Us form and the submit button is disabled. The submit button is only enabled if all fields are filled and the entries are valid.

Currently, my issue is after I entered all the fields with valid entries, the button still not show up. However, after entering in all the fields with valid input and I click on the name or email input box and type a character at the end, then the submit button becomes active. I think there is some async issue with my checkValidation function and I am not sure how to fix it.

enter image description here

import React, { Component } from 'react'
import axios from 'axios'
import '../css/ContactUs.css';

class ContactUs extends Component {
    constructor(props) {
        super(props)
    
        this.state = {
             name: '',
             email: '',
             birthDate: '',
             emailConsent: false,
             disableSubmitButton: true
        }
    }

    changeHandler = e => {
        const nameSelect = e.target.name
        const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
        this.setState({
            [nameSelect]: value
        })
        this.checkValidation()
    }

    checkValidation = e => {
        
        const { name, email, birthDate, emailConsent, disableSubmitButton } = this.state
        const validCharacters = /^[a-zA-Z ]+$/
        const validEmail = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        const today = new Date();
        const birthdate = new Date(birthDate);
        if (
            !(name.length === 0) &&
            name.match(validCharacters) &&
            !(email.length === 0) &&
            validEmail.test(email) &&
            emailConsent === true &&
            birthdate < today
        ) {
            this.setState({
            disableSubmitButton: false
        }, () => console.log('passed'))}
    }

    clearHandler = e => {
        this.setState({
             name: '',
             email: '',
             birthDate: '',
             emailConsent: false
        })
        console.log('clicked clear')
    }

    handleSubmit = e => {
        const { name, email, birthDate, emailConsent } = this.state
        e.preventDefault()
        console.log(this.state);
        axios.post('https://my-json-server.typicode.com/xxxxx/users', {name : name, email: email, birthDate: birthDate, emailConsent: emailConsent })
        .then(response => {
            console.log(response)
        })
        .catch(error => {
            console.log(error)
        })
    }

    render() {
        const { name, email, birthDate, emailConsent, disableSubmitButton } = this.state
        
        return (
            <div className="container">
                <h1>Contact Us</h1>
                <form onSubmit={this.handleSubmit}>
                    <label>
                        Name
                        <input 
                            className="text"
                            name="name"
                            type="text"
                            value={name}
                            onChange={this.changeHandler}
                        />
                    </label>
                    <label>
                        Email
                        <input 
                            className="text"
                            name="email"
                            type="email"
                            value={email}
                            onChange={this.changeHandler}
                        />
                    </label>
                    <label>
                        Birth Date
                        <input 
                            className="text"
                            name="birthDate"
                            type="date"
                            value={birthDate}
                            onChange={this.changeHandler}
                        />
                    </label>
                    <label className="checkbox">
                        <input 
                            
                            name="emailConsent"
                            type="checkbox"
                            checked={emailConsent}
                            onChange={this.changeHandler}
                        />
                        I agree to be contact via email.
                    </label>
                    <div className="float-right">
                        <button className="clear" type="button" onClick={this.clearHandler}>Clear</button>
                        <input disabled={disableSubmitButton} className={disableSubmitButton ? 'submit-inactive' : 'submit'} type="submit" value="Submit"></input>
                    </div>
                </form>
            </div>
        )
    }
}

export default ContactUs

1
  • It’s not your bug, but I notice your checkValidation function is defined like checkValidation = e => {…}, taking an e parameter. This e parameter is never passed to it or used, so you should write checkValidation = () => {…} or checkValidation() {…}. Commented Sep 23, 2020 at 22:28

3 Answers 3

2

I guessing this is because the change event is fired only when one leaves the input. Try to replace, in the render method, onChange by onInput.

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

2 Comments

In plain JavaScript you would be right, but in React, onChange actually works the same as onInput – it listens for input events. So onChange can’t be the problem.
Oops sorry about that, I didn't know, thank you for pointing it out
1

this.setState(…) is asynchronous so, in changeHandler function this.checkValidation() is executed after the state has been updated. This is why it only works when you add one character after the form beeing valid.

3 Comments

How do I fix it so that the users don't have to do that extra step and have the submit button show up?
You could add this.checkValidation() inside this.setState(…) 2nd parameter function (where you have console.log in checkValidation declaration). Or, probably better, as the documentation suggests use componentDidUpdate()
Thanks, I use the componentDidUpdate and it works. I also need to make some update on the if statement in order to make it works. I posted my solution here. If you find out an easier way to do it, please let me know.
0

Someone here suggested me to use componentDidUpdate and it works. If you know another way to do it, please let me know. Thanks!

import React, { Component } from 'react'
import axios from 'axios'
import '../css/ContactUs.css';

class ContactUs extends Component {
    constructor(props) {
        super(props)
    
        this.state = {
             name: '',
             email: '',
             birthDate: '',
             emailConsent: false,
             disableSubmitButton: true
        }
    }

    changeHandler = e => {
        const nameSelect = e.target.name
        const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
        this.setState({
            [nameSelect]: value
        })
    }

    clearHandler = e => {
        this.setState({
             name: '',
             email: '',
             birthDate: '',
             emailConsent: false
        })
        // console.log('clicked clear')
    }

    handleSubmit = e => {
        const { name, email, birthDate, emailConsent } = this.state
        e.preventDefault()
        // console.log(this.state);
        axios.post('https://my-json-server.typicode.com/xxxxx/users', JSON.stringify({name : name, email: email, birthDate: birthDate, emailConsent: emailConsent }))
        .then(response => {
            console.log(response)
        })
        .catch(error => {
            console.log(error)
        })
        alert('Submitted')
    }

    // componentDidUpdate will check all field inputs are complete and valid. If so, it toggles the state of disableSubmitButton and the submit button becomes available and vice versa
    componentDidUpdate() {
        const { name, email, birthDate, emailConsent, disableSubmitButton } = this.state
        const validCharacters = /^[a-zA-Z ]+$/
        const validEmail = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        const today = new Date();
        const birthdate = new Date(birthDate);
        if (
            disableSubmitButton === true &&
            !(name.length === 0) &&
            name.match(validCharacters) &&
            !(email.length === 0) &&
            validEmail.test(email) &&
            emailConsent === true &&
            birthdate < today &&
            isNaN(birthdate) === false
        ) {
            this.setState({
            disableSubmitButton: false
        })} else if (
            disableSubmitButton === false &&
            ((name.length === 0) ||
            !(name.match(validCharacters)) ||
            (email.length === 0) ||
            !(validEmail.test(email)) ||
            emailConsent !== true ||
            birthdate >= today ||
            isNaN(birthdate) === true)
        ) {
            this.setState({
            disableSubmitButton: true
        })}
    }

    render() {
        const { name, email, birthDate, emailConsent, disableSubmitButton } = this.state
        
        return (
            <div className="container">
                <h1>Contact Us</h1>
                <form onSubmit={this.handleSubmit}>
                    <label>
                        Name
                        <input 
                            className="text"
                            name="name"
                            type="text"
                            value={name}
                            onChange={this.changeHandler}
                        />
                    </label>
                    <label>
                        Email
                        <input 
                            className="text"
                            name="email"
                            type="email"
                            value={email}
                            onChange={this.changeHandler}
                        />
                    </label>
                    <label>
                        Birth Date
                        <input 
                            className="text"
                            name="birthDate"
                            type="date"
                            value={birthDate}
                            onChange={this.changeHandler}
                        />
                    </label>
                    <label className="checkbox">
                        <input 
                            
                            name="emailConsent"
                            type="checkbox"
                            checked={emailConsent}
                            onChange={this.changeHandler}
                        />
                        I agree to be contact via email.
                    </label>
                    <div className="float-right">
                        <button className="clear" type="button" onClick={this.clearHandler}>Clear</button>
                        <input disabled={disableSubmitButton} className={disableSubmitButton ? 'submit-inactive' : 'submit'} type="submit" value="Submit"></input>
                    </div>
                </form>
            </div>
        )
    }
}

export default ContactUs

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.