Search code examples
reactjsformsvalidationbuttonmessage

How to prevent the button Submit form works when there is an error for form validation?


I have built a form and added validation for this form, required fields. When clicking on the button "Calculate saving ranges" if no entry filled, it still links to the result page. How to prevent the button links to the result page when there is an error message displayed, otherwise it works? My code is here

import React, { Component } from "react";
import "./style.css";
import { Button, Form, Row, Col} from "react-bootstrap";

class Calculator extends Component {
  constructor(props) {
    super(props);
    this.state = {
      numberBuilding: "",
      squareFootage: "",
      tenant: "",
      floor: "",
      bill: "",
      zipcode: "",
      squareFootageError: "",
      floorError: "",
      zipcodeError: ""
    };
  }

  handleSquare = (event) => {
    this.setState({ squareFootage: event.target.value });
  };

  handleFloor = (event) => {
    this.setState({ floor: event.target.value });
  };

  handleZipCode = (event) => {
    this.setState({ zipcode: event.target.value });
  };

  closeModal = () => this.setState({ isOpen: false });
  validate = () =>{
    let squareFootageError = " ";
    let floorError = " ";
    let zipcodeError = " ";

    if (!this.state.squareFootage){
      squareFootageError = "Please input a number, e.g. 12300";
    }

    if (!this.state.floor){
      floorError = "Please input a number of floors, e.g. 12";
    }

    if (!this.state.zipcode){
      zipcodeError = " Please input a ZIP code or PIN code if outside the US e.g., 10023 or L5V1N3";
    }

    if (squareFootageError || floorError || zipcodeError){
      this.setState({squareFootageError, floorError, zipcodeError });
      return false;
    }
    return true;
  }

  handleSubmit = (event) => {
    event.preventDefault();
    const isValid = this.validate();
    if (isValid){
      console.log(this.state);
    }
    this.props.history.push({
      isOpen: true,
      state: {
        value:
          "$" +
          Math.floor(1.69 * this.state.squareFootage * (10 / 100)) +
          "- $" +
          Math.floor(1.69 * this.state.squareFootage * (30 / 100))
      }
    });
  
  };

  render() {
    return (
      <div className="calculator">
          
           {
          /*Condition*/ !this.state.isOpen ? (
            /** if true return form */

            <Form.Group as={Row} controlId="formHorizontalFootage">
              <Form.Label column sm={6}>
                Square footage of buildings*
              </Form.Label>
              <Col sm={6}>
                <Form.Control
                  type="squareFootage"
                  placeholder="sq ft"
                  value={this.state.squareFootage}
                  onChange={this.handleSquare}
                  required
                />
                <div style={{fontSize: 14, color: 'red'}}>{this.state.squareFootageError}</div>
                <Form.Text className="text-muted">
                Please input a number, e.g. 12300
                </Form.Text>
              </Col>
            </Form.Group>

           
            <Form.Group as={Row} controlId="formHorizontalNumber">
              <Form.Label column sm={6}>
                Number of floors*
              </Form.Label>
              <Col sm={6}>
                <Form.Control
                  type="number"
                  placeholder="number"
                  value={this.state.floor}
                  onChange={this.handleFloor}
                  required
                />
                <Form.Text className="text-muted">
                  Total number of floors across all buildings
                </Form.Text>
                <div style={{fontSize: 14, color: 'red'}}>{this.state.floorError}</div>
              </Col>
            </Form.Group>

            

            <Form.Group as={Row} controlId="formPlaintextZip">
              <Form.Label column sm={6}>
                Zip Code*
              </Form.Label>
              <Col sm={6}>
                <Form.Control
                  type="zipcode"
                  placeholder="xxxxx"
                  value={this.state.zipcode}
                  onChange={this.handleZipCode}
                  required
                />
                <div style={{fontSize: 14, color: 'red'}}>{this.state.zipcodeError}</div>
                <Form.Text className="text-muted">
                Please input a ZIP code or PIN code if outside the US e.g., 10023 or L5V1N3
                </Form.Text>
              </Col>
            </Form.Group>

            <Button onClick={this.handleSubmit}>
              Calculate your Savings Range
            </Button>
            <Form.Text className="text-muted">* Required Field</Form.Text>
          </Form>

) : (
  /** else return yourresult div */
  <div className="result">
    <h2>You could save between</h2>
    <h1>{this.state.value}</h1>
    <h2> annually </h2>
    &nbsp;&nbsp;
    <button onClick={this.handle}
    class="btn btn-secondary">
        Use Calculator again</button>
  </div>
)
}


</div>
    );
  }
}

export default Calculator;

You can find my code is here as well: https://codesandbox.io/s/calculation-form-uxip8?file=/src/components/Calculator.jsx

Can someone stop by and give me some help? Thanks a lot!


Solution

  • You can return if isValid is false.

    Forked your code here: https://codesandbox.io/s/calculation-form-forked-j3uhz?file=/src/components/Calculator.jsx

        if (isValid) {
          console.log(this.state);
        } else {
          return;
        }
    

    Also, isValid never becomes true because of these lines:

        let squareFootageError = " ";
        let floorError = " ";
        let zipcodeError = " ";
    

    by setting default values to " " (a string composed of a space), this condition: if (squareFootageError || floorError || zipcodeError) always works, and thus validate() never returns true. If it is not clear I can also edit your codesandbox to show you.

    You shall set default values to empty strings like this:

        let squareFootageError = "";
        let floorError = "";
        let zipcodeError = "";