I've written this calculator for payment cost. Now I need to check if the input isn't empty + is a number, otherwise throw an error to say that "The field can't be empty". I started adding it but got confused along in the process. What's the best/cleanest way to handle error handling in this example? Maybe I should put the error handling job into a separate component?
import React, { Component } from "react";
import styles from "./../styles.module.less";
class Calc extends Component {
constructor(props) {
super(props);
this.state = {
popoverOpen: false,
cost: 0,
homePrice: 0,
downPaymentAmt: 0,
downPaymentPrc: 0,
termOfLoan: 0,
annualInterestRate: 0,
formError: '',
inputValid: false
};
}
handleStateChange = e => {
const {
target: { name, value },
} = e;
this.setState({ [name]: value });
};
handleCostChange = () => {
const {
homePrice,
downPaymentAmt,
termOfLoan,
annualInterestRate,
} = this.state;
const principal = homePrice - downPaymentAmt;
const lengthOfLoan = 12 * termOfLoan;
const percentageRate = annualInterestRate / 1200;
// Formula M = P[i(1+i)^n]/[(1+i)^n -1]
const cost =
(principal * percentageRate) /
(1 - Math.pow(1 + percentageRate, lengthOfLoan * -1)).toString();
this.setState({
cost: cost.toFixed(2),
});
};
render() {
return (
<div>
<div className={styles.row}>
<div className={styles.col12}>
<h1 className={styles.calch1}>
Your home-buying by numbers
</h1>
<div
className={`${styles.positionRelative} ${
styles.formGroup
}`}>
<label htmlFor="name" >
Home price
</label>
<label s" formError={this.state.formError}>The field can't be empty</label>
<div className={styles.inputGroup}>
<div className={styles.inputGroupPrepend}>
<span className={styles.inputGroupText}>
$
</span>
</div>
<input
type="text"
id="input3-group1"
className={styles.formControl}
name="homePrice"
value={this.state.value}
onChange={this.handleStateChange}
placeholder="Amount of home's selling price"
/>
</div>
</div>
</div>
</div>
<div className={styles.row}>
<div className={styles.col12}>
<div
className={`${styles.positionRelative} ${
styles.formGroup
}`}>
<label htmlFor="name" className="">
Loan program
</label>
<div className={styles.inputGroup}>
<input
type="text"
id="name"
required=""
className={styles.formControl}
name="termOfLoan"
value={this.state.value}
onChange={this.handleStateChange}
placeholder="Original number of years to pay off your mortgage"
/>
</div>
</div>
</div>
</div>
<div className={`${styles.col6} ${styles.colsm4}`}>
<div
className={`${styles.positionRelative} ${
styles.formGroup
}`}>
<label
htmlFor="name"
className=""
style={{ display: "block" }}>
</label>
<button
className={`${styles.btn} ${
styles.btnWarning
} ${styles.btnSm}`}
style={{
fonSize: 16,
height: "35px",
color: "white",
}}
onClick={this.handleCostChange}>
Calculate!
</button>
</div>
</div>
</div>
<div className={styles.row}>
<div className={styles.col}>
<h2 className={styles.calch2}>
Your monthly mortgage
</h2>
<div className={styles.tableResponsive}>
<table
className={`${styles.borderLess} ${
styles.table
}`}>
{/* <thead>
<tr>
<th>Estimated monthly</th>
<th>taxes</th>
<th>Insurance</th>
<th>P&I</th>
</tr>
</thead> */}
<tbody>
<tr className={styles.output}>
<td>
${this.state.cost.toLocaleString()}
</td>
<td className={styles.tdlabel}>
PER MONTH
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
);
}
}
export default Calc;
You can listen for onBlur
event. It occurs when the user leaves an input field. So, add onBlur
event listener in your input field.
eg : For homePrice
<input
type="text"
id="input3-group1"
className={styles.formControl}
name="homePrice"
// assign value as this.state.homePrice
value={this.state.homePrice}
// Add onBlur and use handleValidation event handler
onBlur={this.handleValidation}
onChange={this.handleStateChange}
placeholder="Amount of home's selling price"
/>
// for testing add this line just below the input field
// it will display form error
{ this.state.formError && <span>{this.state.formError} </span> }
Now add handleValidation
method to your component
handleValidation = (e) => {
let { value } = e.target
// check if value is empty or not
if (value.trim().length === 0) {
this.setState({formError: 'Input field is required'})
return
// check if value is number or not
} else if (isNaN(Number(value))) {
this.setState({formError: 'Input field value must be a number'})
return
} else {
this.setState({ formError: ''})
}
}
UPDATE
handleCostChange = (e) => {
// for testing only not needed
let { value } = e.target;
// Checking whether "e.target.value" on button is empty or not
console.log('some',value,'text') // some text
console.log(value.trim().length === 0) // true
const {
homePrice,
downPaymentAmt,
termOfLoan,
annualInterestRate,
} = this.state;
// updates
if (homePrice.trim().length === 0) {
this.setState({formError: 'Input Fields are required'})
return
} else if (isNaN(Number(homePrice))) {
this.setState({formError: 'Input Fields must be number'})
return
}
const principal = homePrice - downPaymentAmt;
const lengthOfLoan = 12 * termOfLoan;
const percentageRate = annualInterestRate / 1200;
// Formula M = P[i(1+i)^n]/[(1+i)^n -1]
const cost =
(principal * percentageRate) /
(1 - Math.pow(1 + percentageRate, lengthOfLoan * -1)).toString();
this.setState({
cost: cost.toFixed(2),
// update
formError: ''
});
};
And also change
this.state = {homePrice: 0}
to
this.state = {homePrice: ''}
This is needed because I have used trim()
method which is a string method. So when you submit without touching the input field you will get an error.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.