ReactJS form validation - javascript

I have simple form validation for react. I made this from this source
http://www.dotnetawesome.com/2016/02/create-simple-forms-with-validation-in-react-js.html
there is my code. when I submit the form input error occurred inside of the isValid function. please help me to fix this.
AddMember page
class AddMember extends Component {
constructor(props) {
super(props);
this.state = {
loading : true,
formData: {
fname : "",
lname : "",
address1: "",
address2: "",
city : "",
mobile : "",
role : "",
email : "",
gender : ""
},
fields : []
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
this.register = this.register.bind(this);
}
componentDidMount() {
document.title = globals.title + "Add New Member";
setTimeout(() => {
this.setState({loading: false})
}, 500);
}
handleSubmit = (e) => {
e.preventDefault();
let validForm = true;
this.state.fields.forEach(function (field) {
console.log(field.refs[field.props.name]);
if (typeof field.isValid === "function") {
let validField = field.isValid(field.refs[field.props.name]);
validForm = validForm && validField
}
});
if (validForm) {
console.log(this.state.fields);
}
};
handleChange = (name) => (value) => {
let formData = {
[name]: value
};
this.setState({
formData: formData
})
};
register (field) {
let s = this.state.fields;
s.push(field);
this.setState({fields: s});
console.log("ss");
};
render() {
const {classes} = this.props;
if (this.state.loading) {
return (
<div className={classes.posRelative}>
<CircularProgress size={80} className={classes.progress}/>
</div>
)
}
return (
<Grow in={true} style={{transformOrigin: "0 0 0"}}>
<Paper className={classes.root}>
<form
onSubmit={this.handleSubmit}
noValidate>
<Grid container spacing={16}>
<Grid item xs={12} sm={6}>
<MuiValidator placeholder={"First Name"} name={"fname"} type={"email"}
onChange={this.handleChange("fname")} value={this.state.formData.fname}
inputProps={{required:true}} onComponentMounted={this.register} fullWidth={true}/>
</Grid>
</Grid>
<Button type={"submit"} variant={"raised"} color={"primary"}>Submit</Button>
</form>
</Paper>
</Grow>
);
}
}
validation component
class MuiValidator extends Component {
constructor(props) {
super(props);
this.state = {
error : "",
errorMsg: ""
};
this.isValid = this.isValid.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange (e) {
this.props.onChange(e.target.value);
let isValidField = this.isValid(e.target);
// console.log(e.target.appendChild());
console.log(isValidField);
};
//Validation function
isValid (input) {
console.log(input);
//check required field
if (input.getAttribute("required") !== null && input.value === "") {
this.setState({error: true,errorMsg:'This field is required'});
return false
} else {
this.setState({error: false,errorMsg:''});
// input.nextSibling.textContent = "";
}
if (input.getAttribute("type") === "email" && input.value !== "") {
if (!this.validateEmail(input.value)) {
this.setState({error: true, errorMsg: "Please enter valid email address"})
return false
} else {
this.setState({error: false,errorMsg:''});
}
}
return true;
};
validateEmail = (value) => {
let re = /^(([^<>()[\]\\.,;:\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,}))$/;
return re.test(value);
};
componentDidMount() {
if (this.props.onComponentMounted) {
this.props.onComponentMounted(this);
}
}
render() {
const {error,errorMsg} = this.state;
return (
<div>
<FormControl fullWidth={this.props.fullWidth} margin={"normal"} error={!!error}>
<InputLabel>First Name</InputLabel>
<Input name={this.props.name} type={this.props.type} placeholder={this.props.placeholder}
value={this.props.value} onChange={this.handleChange}
inputProps={this.props.inputProps} ref={this.props.name}/>
{error && <FormHelperText>{errorMsg}</FormHelperText>}
</FormControl>
</div>
);
}
}
I have no idea how can fix this please help me...

thanks all. finally, I found a solution. I changed the handle submit function like this
handleSubmit = (e) => {
e.preventDefault();
let validForm = true;
this.state.fields.forEach((field) => {
//create input element
let elm = document.createElement("input");
for (let attr in field.refs[field.props.name].props) {
if (attr !== "onChange" && attr !== "inputProps") {
elm.setAttribute(attr, field.refs[field.props.name].props[attr]);
elm.removeAttribute("onChange");
}
if (attr === "inputProps") {
for (let props in field.refs[field.props.name].props.inputProps) {
elm.setAttribute(props, field.refs[field.props.name].props.inputProps[props]);
}
}
}
if (typeof field.isValid === "function") {
let validField = field.isValid(elm);
validForm = validForm && validField
}
});
if (validForm) {
console.log(this.state.fields);
}
};

The problem resides in the on submit because the input is not retrieved correctly (I need a working code but it seems refs are not set correctly) while on event you pass the exact reference to the field coming directly from event. Check your refs and everything should work ok. As said from #SandipNirmal Formik has a great validation feature that you are substantially replicating.

Related

Wrong input validation

I want to validate all of my inputs in react
My validation code looks like this:
let isValid = {
name: false,
address: false,
postcode: false,
phone: false,
email: false
};
const validateInput = (e) => {
let currentInput = e.target
if (currentInput.name === 'name') {
if (currentInput.value !== 'undefined' && currentInput.value.match(/^[a-zA-Z]+$/)) {
isValid.name = true;
} else {
isValid.name = false;
}
}
if (currentInput.name === 'address') {
if (currentInput.value !== 'undefined') {
isValid.address = true;
} else {
isValid.address = false;
}
}
if (currentInput.name === 'postcode') {
if (currentInput.value !== undefined && currentInput.value.match(/^[0-9]+[-]+[0-9]+$/) && currentInput.value.length > 4) {
isValid.postcode = true;
} else {
isValid.postcode = false;
}
}
if (currentInput.name === 'phone') {
if (currentInput.value !== 'undefined' && currentInput.value.match(/^[0-9]+$/) && currentInput.value.length > 7) {
isValid.phone = true;
} else {
isValid.phone = false;
}
}
if (currentInput.name === 'email') {
if (currentInput.value !== 'undefined' && currentInput.value.match(/^(([^<>()[\]\\.,;:\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,}))$/)) {
isValid.email = true;
} else {
isValid.email = false;
}
}
console.log(isValid)
}
For example when i type correct value in "Name" isValid.name gets value true, then when i write somethink in "address" isValid.address gets true, but isValid.name false
How to fix it?
{requiredInformations.map((el) => (
<>
<Label>{el.label}</Label>
<Input type={el.type} name={el.name} required onChange={(e) => { getInputValue(e); validateInput(e) }} />
</>
))}
I suggest you try to use react-joi library for validation React-Joi-Validation
Its easy and simple to use, and you can achieve what you are trying here in your code by just reading the first page on their npm package main page.
You need to get yourself familiar with terms like "state"
, "props", "component lifecycle", etc. Build a simple component using a guide on youtube, you can find plenty of them.
Meanwhile, here is a simple component that validates inputs:
function App() {
const [name, setName] = React.useState('');
const [address, setAddress] = React.useState('');
const isValid = React.useMemo(() => {
const result = {
name: false,
address: false,
};
if (name.match(/^[a-zA-Z]+$/)) {
result.name = true;
} else {
result.name = false;
}
if (address !== '') {
result.address = true;
} else {
result.address = false;
}
return result;
}, [name, address]);
return (
<div>
<input
placeholder="Name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
{isValid.name ? <p>Name is valid</p> : <p>Name is invalid</p>}
<br />
<input
placeholder="Address"
value={address}
onChange={(e) => setAddress(e.target.value)}
/>
{isValid.address ? <p>Adress is valid</p> : <p>Adress is invalid</p>}
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root">
</div>

Validation check in reactjs issue

Why I am not able to see validation alert clicking on the done button when everything is empty once form open even validation checks are proper ?
Basically form opens i don't type anything and click on done button so all validation checks should work and show text 'Required.Please enter your given name.' but it is not showing ?
Where is the issue which causes the state to be blank at the end
const addSecondaryContact = inject('apptContacts')(observer((props) => {
const {
i18n, nbnContact, apptContacts, backButtonContent,
} = props;
const { updatePrimaryContact } = apptContacts;
const CMS = i18n.appointmentManager.editAppointmentContact;
const [state, setState] = useState({
data: {
firstName: '',
lastName: '',
number: '',
},
firstNameValid: '',
lastNameValid: '',
numberValid: '',
});
const validFirstName = () => {
console.log(state.data.firstName);
if (!state.data.firstName) {
console.log('frstname1');
return 'Required.Please enter your given name.';
}
if (!/^[A-Za-z]+$/.test(state.data.firstName)) {
console.log('frstname2');
return 'Invalid entry.Please use letters only.';
} if (state.data.firstName.length === 1) {
console.log('frstname3');
return 'Invalid entry.More than one character is required';
}
console.log('&&&&');
return '';
};
const validLastName = () => {
console.log('988');
if (!state.data.lastName) { console.log('lastname'); return 'Required.Please enter your given name.'; }
if (!/^[A-Za-z]+$/.test(state.data.lastName)) {
return 'Invalid entry.Please use letters only.';
} if (state.data.lastName.length === 1) {
return 'Invalid entry.More than one character is required';
}
return '';
};
const validNumber = async () => {
console.log('777');
if (!state.data.number) { return 'Required.Please enter your mobile number.'; }
if (state.data.number.substr(0, 2) !== '04') {
return 'Invalid entry.Please enter your 10-digit mobile number starting with 04.';
} if (state.data.number.length !== 10) {
return 'Invalid entry.Please enter your 10-digit mobile number starting with 04.';
} if (state.data.number.length === 1) {
return 'Invalid entry.More than one number is required';
}
return '';
};
const valid = async () => {
console.log('milan');
setState({
...state,
firstNameValid: validFirstName(),
lastNameValid: validLastName(),
numberValid: validNumber(),
});
console.log(state.firstNameValid);
console.log(state.lastNameValid);
console.log(state.numberValid);
};
const handleTextareaChange = (event) => {
console.log('%%%');
const { data } = state;
data[event.target.name] = event.target.value;
setState({
...state,
data,
});
valid();
};
const saveButton = async () => {
console.log(state);
await valid();
if (valid()) {
console.log(state.firstNameValid);
console.log(state.lastNameValid);
console.log(state.numberValid);
if (!state.firstNameValid && !state.lastNameValid && !state.numberValid) {
const personName = `${state.data.firstName} ${state.data.lastName}`;
const primaryContact = {
name: personName,
phoneNumber: state.data.number,
// updatePrimaryContact(primaryContact)
};
// updatePrimaryContact(primaryContact)
backButtonContent();
}
}
};
return (
<div>
<VerticalSpacing size={ABLE_SPACING_SIZE.spacing4x} />
<h1 tabIndex="-1" className="HeadingB mt-sheet-heading">
{CMS.heading2}
</h1>
<VerticalSpacing size={ABLE_SPACING_SIZE.spacing3x} />
<TextField id="givenName" name="firstName" label={CMS.name} onChange={handleTextareaChange} value={state.data.firstName} />
{state.firstNameValid && (
<Alert variant="error" inline>
<p>
{state.firstNameValid}
</p>
</Alert>
)}
<VerticalSpacing size={ABLE_SPACING_SIZE.spacing3x} />
<TextField id="familyName" name="lastName" label={CMS.familyName} onChange={handleTextareaChange} value={state.data.lastName} />
{state.lastNameValid && (
<Alert variant="error" inline>
<p>
{state.lastNameValid}
</p>
</Alert>
)}
<VerticalSpacing size={ABLE_SPACING_SIZE.spacing3x} />
<TextField id="mobileNumber" name="number" label={CMS.mobile} onChange={handleTextareaChange} value={state.data.number} />
{state.numberValid && (
<Alert variant="error" inline>
<p>
{state.numberValid}
</p>
</Alert>
)}
<VerticalSpacing size={ABLE_SPACING_SIZE.spacing4x} />
<ActionButton className={styles.saveCta} variant="HighEmphasis" label={CMS.saveCTA} onClick={() => saveButton()} />
</div>
);
}));
export default addSecondaryContact;
You had two main issues:
you state update is not proper - you set state on multiple occasions
you had async in your validNumber method - which causes blank output
Here is the code i modify from your code - maybe it can help you. I removed extra components in order to remove dependencies and used only plain html.
Demo: https://codesandbox.io/s/upbeat-feynman-w3odj?file=/App.js
import "./styles.css";
import React from "react";
export default function App() {
const [state, setState] = React.useState({
data: {
firstName: "",
lastName: "",
number: ""
},
firstNameValid: "",
lastNameValid: "",
numberValid: ""
});
const validFirstName = () => {
console.log(state.data.firstName);
let result = "";
if (!state.data.firstName) {
console.log("frstname1");
result = "Required.Please enter your given name.";
}
if (!/^[A-Za-z]+$/.test(state.data.firstName)) {
console.log("frstname2");
result = "Invalid entry.Please use letters only.";
}
if (state.data.firstName.length === 1) {
console.log("frstname3");
result = "Invalid entry.More than one character is required";
}
console.log("&&&&");
return result;
};
const validLastName = () => {
console.log("988");
if (!state.data.lastName) {
console.log("lastname");
return "Required.Please enter your given name.";
}
if (!/^[A-Za-z]+$/.test(state.data.lastName)) {
return "Invalid entry.Please use letters only.";
}
if (state.data.lastName.length === 1) {
return "Invalid entry.More than one character is required";
}
return "";
};
const validNumber = () => {
console.log("777");
if (!state.data.number) {
return "Required.Please enter your mobile number.";
}
if (state.data.number.substr(0, 2) !== "04") {
return "Invalid entry.Please enter your 10-digit mobile number starting with 04.";
}
if (state.data.number.length !== 10) {
return "Invalid entry.Please enter your 10-digit mobile number starting with 04.";
}
if (state.data.number.length === 1) {
return "Invalid entry.More than one number is required";
}
return "";
};
const valid = async () => {
console.log("milan");
setState({
...state,
firstNameValid: validFirstName(),
lastNameValid: validLastName(),
numberValid: validNumber()
});
console.log(state.firstNameValid);
console.log(state.lastNameValid);
console.log(state.numberValid);
};
const handleTextareaChange = (event) => {
let validRes = "";
let key = "";
if (event.target.name === "firstName") {
validRes = validFirstName();
key = "firstNameValid";
}
if (event.target.name === "lastName") {
validRes = validLastName();
key = "firstNameValid";
}
if (event.target.name === "number") {
validRes = validNumber();
key = "numberValid";
}
console.log("234", validRes);
setState({
...state,
data: { ...state.data, [event.target.name]: event.target.value },
// [key]:
firstNameValid: validFirstName(),
lastNameValid: validLastName(),
numberValid: validNumber()
});
// valid();
};
const saveButton = async () => {
console.log(state);
await valid();
if (valid()) {
console.log(state.firstNameValid);
console.log(state.lastNameValid);
console.log(state.numberValid);
}
};
return (
<div>
<h1 tabIndex="-1" className="HeadingB mt-sheet-heading">
'CMS.heading2'
</h1>
<input
type="text"
id="givenName"
name="firstName"
label="CMS.name"
onChange={handleTextareaChange}
value={state.data.firstName}
/>
{state.firstNameValid && <p>{state.firstNameValid}</p>}
<input
type="text"
id="familyName"
name="lastName"
label="CMS.familyName"
onChange={handleTextareaChange}
value={state.data.lastName}
/>
{state.lastNameValid && <p>{state.lastNameValid}</p>}
<input
type="text"
id="mobileNumber"
name="number"
label="CMS.mobile"
onChange={handleTextareaChange}
value={state.data.number}
/>
{state.numberValid && <p>{state.numberValid}</p>}
<button
variant="HighEmphasis"
label="CMS.saveCTA"
onClick={() => saveButton()}
/>
</div>
);
}

How to avoid input value reset in Reactjs?

I am referring to this tutorial for simple react autocomplete https://www.digitalocean.com/community/tutorials/react-react-autocomplete
But I have a slightly different requirement. Instead of typing something on the input field, I want all the suggestions to come up on clicking the input field. I am basically implementing a requirement where on clicking the input field, it should show user what are the available options.
Here is my sandbox https://codesandbox.io/s/distracted-easley-wdm5x
Specifically in the Autocomplete.jsx file (as mentioned below)
import React, { Component, Fragment } from "react";
import PropTypes from "prop-types";
class Autocomplete extends Component {
static propTypes = {
suggestions: PropTypes.instanceOf(Array)
};
static defaultProps = {
suggestions: []
};
constructor(props) {
super(props);
this.state = {
// The active selection's index
activeSuggestion: 0,
// The suggestions that match the user's input
filteredSuggestions: [],
// Whether or not the suggestion list is shown
showSuggestions: false,
// What the user has entered
userInput: ""
};
}
onChange = (e) => {
const { suggestions } = this.props;
const userInput = e.currentTarget.value;
// Filter our suggestions that don't contain the user's input
const filteredSuggestions = suggestions.filter(
(suggestion) =>
suggestion.toLowerCase().indexOf(userInput.toLowerCase()) > -1
);
this.setState({
activeSuggestion: 0,
filteredSuggestions,
showSuggestions: true,
userInput: e.currentTarget.value
});
};
onClick = (e) => {
this.setState({
activeSuggestion: 0,
filteredSuggestions: [],
showSuggestions: false,
userInput: e.currentTarget.innerText
});
};
onClick2 = (e) => {
console.log("text check", e.currentTarget.innerText);
if (e.currentTarget.innerText === "") {
const { suggestions } = this.props;
const filteredSuggestions = suggestions;
this.setState({
activeSuggestion: 0,
filteredSuggestions,
showSuggestions: true,
userInput: e.currentTarget.innerText
});
}
};
onKeyDown = (e) => {
const { activeSuggestion, filteredSuggestions } = this.state;
// User pressed the enter key
if (e.keyCode === 13) {
this.setState({
activeSuggestion: 0,
showSuggestions: false,
userInput: filteredSuggestions[activeSuggestion]
});
}
// User pressed the up arrow
else if (e.keyCode === 38) {
if (activeSuggestion === 0) {
return;
}
this.setState({ activeSuggestion: activeSuggestion - 1 });
}
// User pressed the down arrow
else if (e.keyCode === 40) {
if (activeSuggestion - 1 === filteredSuggestions.length) {
return;
}
this.setState({ activeSuggestion: activeSuggestion + 1 });
}
};
render() {
const {
onChange,
onClick2,
onClick,
onKeyDown,
state: {
activeSuggestion,
filteredSuggestions,
showSuggestions,
userInput
}
} = this;
let suggestionsListComponent;
if (showSuggestions) {
if (filteredSuggestions.length) {
suggestionsListComponent = (
<ul className="suggestions">
{filteredSuggestions.map((suggestion, index) => {
let className;
// Flag the active suggestion with a class
if (index === activeSuggestion) {
className = "suggestion-active";
}
return (
<li className={className} key={suggestion} onClick={onClick}>
{suggestion}
</li>
);
})}
</ul>
);
} else {
suggestionsListComponent = (
<div className="no-suggestions">
<em>No suggestions, you're on your own!</em>
</div>
);
}
}
return (
<Fragment>
<input
type="text"
onChange={onChange}
onKeyDown={onKeyDown}
value={userInput}
onClick={onClick2}
/>
{suggestionsListComponent}
</Fragment>
);
}
}
export default Autocomplete;
In the input element in return section,
<input
type="text"
onChange={onChange}
onKeyDown={onKeyDown}
value={userInput}
onClick={onClick2}
/>
I have added a onClick functionality that calls the function onClick2.
onClick2 = (e) => {
console.log("text check", e.currentTarget.innerText);
if (e.currentTarget.innerText === "") {
const { suggestions } = this.props;
const filteredSuggestions = suggestions;
this.setState({
activeSuggestion: 0,
filteredSuggestions,
showSuggestions: true,
userInput: e.currentTarget.innerText
});
}
};
My function simply returns all the suggestions back on clicking the input field. I am able to select items from suggestions and it gets put in the input field. But when I click on the input field again, the value disappears.
I want this autocomplete suggestion to only show once on clicking the empty input field and after selecting the item from list, I should be able to edit the value further.
What am I doing wrong?
Input values are not stored into innerText, but in value prop.
Look at this:
onClick2 = (e) => {
console.log("text check", e.currentTarget.innerText);
if (e.currentTarget.value === "") {
const { suggestions } = this.props;
const filteredSuggestions = suggestions;
this.setState({
activeSuggestion: 0,
filteredSuggestions,
showSuggestions: true,
userInput: e.currentTarget.value
});
}
};
This should solve your problem
You are doing the wrong check in onClick2 function. Instead of checking e.currentTarget.innerText === "", it has to be e.target.value as we are validating the text in input field.
onClick2 = (e) => {
console.log("text check", e.target.value);
if (e.target.value === "") {
const { suggestions } = this.props;
const filteredSuggestions = suggestions;
this.setState({
activeSuggestion: 0,
filteredSuggestions,
showSuggestions: true,
userInput: e.currentTarget.innerText
});
}
};
Here is the working link - https://codesandbox.io/s/jolly-meadow-5fr6x?file=/src/Autocomplete.jsx:1344-1711

Trying to set up form validation in my basic todo list app

I am trying to set up validations in my todo list app in react; however this doesn't seem to work. Even if the form is empty the process still goes through and I don't know where the problem is coming from. I am just following a tutorial online since I'm pretty new to this and don't know how to do it myself.
import React from "react";
import * as TodoActions from "../actions/TodoActions";
import TodoStore from "../stores/TodoStore";
import Todo from './Todo.js'
import './Todos.css'
const formValid = ({ formErrors, ...rest }) => {
let valid = true;
Object.values(formErrors).forEach(val => {
val.length > 0 && (valid = false);
});
Object.values(rest).forEach(val => {
val === null && (valid = false);
});
return valid;
};
export default class Todos extends React.Component {
constructor() {
super();
this.state = {
todos: TodoStore.getAll(),
loading: true,
formErrors: {
todo: ""
}
};
TodoActions.receiveTodos()
}
componentWillMount() {
TodoStore.addChangeListener(this.getTodos);
}
componentWillUnmount() {
TodoStore.removeChangeListener(this.getTodos);
}
componentDidUpdate() {
TodoActions.receiveTodos();
}
getTodos = () => {
this.setState({
todos: TodoStore.getAll(),
loading: false
});
}
deleteTodo = (id) => {
TodoActions.deleteTodo(id);
}
addItem = (e) => {
e.preventDefault();
TodoActions.createTodo(this._inputElement.value)
}
handleChange = e => {
e.preventDefault();
const { name, value } = e.target;
let formErrors = { ...this.state.formErrors };
switch (name) {
case "todo":
formErrors.todo =
value.length < 0 ? "Task cannot be empty" : "";
break;
default:
break;
}
this.setState({ formErrors, [name]: value }, () => console.log(this.state));
}
render() {
const { todos } = this.state;
const { formErrors } = this.state;
let TodoComponents;
if (this.state.loading) {
TodoComponents = <h1>Loading...</h1>;
} else if(todos.length) {
TodoComponents = todos.map((todo) => {
return (
<div key={todo.id} className="todo-list">
<Todo key={todo.id} name={todo.name}/>
<div className="todo-btn"><a type="button" onClick={() => this.deleteTodo(todo.id)} className="delete-btn"><i class="fas fa-trash-alt"></i></a></div>
</div>
)
});
} else {
TodoComponents = <p>No tasks to show :)</p>
}
return (
<div className="main-container">
<div className="small-container">
<h1 className="title">All Tasks</h1>
<ul>{TodoComponents}</ul>
<form onSubmit={this.addItem}>
<input ref={(a) => this._inputElement = a} placeholder="Enter Task" className="input-form {formErrors.todo.length < 0 ? 'error' : null}"/>
{formErrors.todo.length < 0 && (
<span className="errorMessage">{formErrors.firstName}</span>
)}
<button type="submit" className="input-btn">Add</button>
</form>
</div>
</div>
);
}
}

Textfields component number validation React js

I have 3 Textfields, what I want to do is just to accept number so if someone put text and click continue the application should display an error saying that just numbers are allowed.
The following code displays an error message if the Textfield is empty and thats ok but the other validation to check if the user inputs text or numbers is pending and I'm stucked.
import React from 'react';
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';
import Divider from 'material-ui/Divider';
import cr from '../styles/general.css';
export default class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
buy_: '',
and_: '',
save_: '',
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event, index, value) {
this.setState({value});
}
clear() {
console.info('Click on clear');
this.setState({
buy_: '',
and_: '',
save_: ''
});
}
validate() {
let isError = false;
const errors = {
descriptionError: ''
};
if (this.state.buy_.length < 1 || this.state.buy_ === null) {
isError = true;
errors.buy_error = 'Field requiered';
}
if (this.state.and_.length < 1 || this.state.and_ === null) {
isError = true;
errors.and_error = 'Field requiered';
}
if (this.state.save_.length < 1 || this.state.save_ === null) {
isError = true;
errors.save_error = 'Field requiered';
}
this.setState({
...this.state,
...errors
});
return isError;
}
onSubmit(e){
e.preventDefault();
// this.props.onSubmit(this.state);
console.log('click onSubmit')
const err = this.validate();
if (!err) {
// clear form
this.setState({
buy_error: '',
and_error: '',
save_error: ''
});
this.props.onChange({
buy_: '',
and_: '',
save_: ''
});
}
}
render() {
return (
<div className={cr.container}>
<div className ={cr.boton}>
<Divider/>
<br/>
</div>
<div className={cr.rows}>
<div>
<TextField
onChange={(e) => {this.setState({buy_: e.target.value})}}
value={this.state.buy_}
errorText={this.state.buy_error}
floatingLabelText="Buy"
/>
</div>
<div>
<TextField
onChange={(e) => {this.setState({and_: e.target.value})}}
value={this.state.and_}
errorText={this.state.and_error}
floatingLabelText="And"
/>
</div>
<div>
<TextField
onChange={(e) => {this.setState({save_: e.target.value})}}
value={this.state.save_}
errorText={this.state.save_error}
floatingLabelText="Save"
/>
</div>
</div>
<div className={cr.botonSet}>
<div className={cr.botonMargin}>
<RaisedButton
label="Continue"
onClick={e => this.onSubmit(e)}/>
</div>
<div>
<RaisedButton
label="Clear"
secondary ={true}
onClick={this.clear = this.clear.bind(this)}
/>
</div>
</div>
</div>
);
}
}
Can someone help me on this please.
Thanks in advance.
You can prevent users from input text by using this :
<TextField
onChange={(e) => {
if(e.target.value === '' || /^\d+$/.test(e.target.value)) {
this.setState({and_: e.target.value})
} else {
return false;
}
}}
value={this.state.and_}
errorText={this.state.and_error}
floatingLabelText="And"
/>
The TextField component can restrict users to entering text using the JavaScript test method:
<TextField
onChange={(e) => {
if(e.target.value == '' || (/\D/.test(e.target.value))) {
this.setState({and_: e.target.value})}
}
else {
return false;
}
}
value={this.state.and_}
errorText={this.state.and_error}
floatingLabelText="And"
/>
Try adding this code in your validate function.
You can use regex to validate your fields for text or numbers like :
import * as RegExp from './RegExpression';
validate() {
let isError = false;
const errors = {
descriptionError: ''
};
if (this.state.buy_ && !RegExp.NAME.test(this.state.buy_)) {
// validation check if input is name
isError = true;
errors.buy_error = 'Invalid name';
}
if (this.state.and_ && !RegExp.NUMBER.test(this.state.and_)) {
// validation check if input is number
isError = true;
errors.and_error = 'Invalid Number';
}
this.setState({
...this.state,
...errors
});
return isError;
}
In RegexExpression file add these validations like this :
export const NAME = /^[a-z ,.'-()"-]+$/i;
export const NUMBER = /^[0-9]*$/ ;
You are not initialising error object in state but accessed in TextField as this.state.and_error. Either you should initialise error in constructor like this.state = { and_error: "" } or initialise error object as
this.state = {
error: {
and_error: "",
buy_error: "",
save_error: ""
}
}
So in your TextField
<TextField
onChange={(e) => {
if(e.target.value === "" || (/\D/.test(e.target.value))) {
this.setState({and_: e.target.value})}
}
else {
return false;
}
}
value={this.state.and_}
errorText={this.state.error.and_error} // If initialised error string access as this.state.and_error
floatingLabelText="And"
/>
Your validate function will be like
validate() {
let isError = false;
const errors = this.state.errors;
if (this.state.buy_.toString().length < 1 || this.state.buy_ === null) {
isError = true;
errors.buy_error = 'Field requiered';
}
if (this.state.and_.toString().length < 1 || this.state.and_ === null) {
isError = true;
errors.and_error = 'Field requiered';
}
if (this.state.save_.toString().length < 1 || this.state.save_ === null) {
isError = true;
errors.save_error = 'Field requiered';
}
this.setState({errors});
return isError;
}
Hope this will heps you!
You can use react-validation for all validation and set rules for validation

Categories