Formik number field accept only positive numbers - reactjs

I have a form in which I have a number field. I am using formik for this. I need to have an input which only accepts positive numbers.
This is the codesandbox url

You should use regex in onChange event of Number input
Sample code:
const App = () => (
<div className="app">
<Formik
initialValues={{ email: "", rank: -2 }}
onSubmit={async values => {
await new Promise(resolve => setTimeout(resolve, 500));
alert(JSON.stringify(values, null, 2));
}}
validationSchema={Yup.object().shape({
email: Yup.string()
.email()
.required("Required")
})}
>
{props => {
const {
values,
touched,
errors,
dirty,
isSubmitting,
handleChange,
handleBlur,
handleSubmit,
handleReset,
setFieldValue
} = props;
return (
<form onSubmit={handleSubmit}>
<label htmlFor="email" style={{ display: "block" }}>
Email
</label>
<input
id="email"
placeholder="Enter your email"
type="text"
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
className={
errors.email && touched.email
? "text-input error"
: "text-input"
}
/>
<label htmlFor="email" style={{ display: "block" }}>
Rank
</label>
<input
id="rank"
placeholder="Enter your email"
type="number"
value={values.rank}
onChange={e => {
e.preventDefault();
const { value } = e.target;
const regex = /^(0*[1-9][0-9]*(\.[0-9]*)?|0*\.[0-9]*[1-9][0-9]*)$/;
if (regex.test(value.toString())) {
setFieldValue("rank", value);
}
}}
onBlur={handleBlur}
/>
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</form>
);
}}
</Formik>
</div>
);
render(<App />, document.getElementById("root"));
Code sanbox link: https://codesandbox.io/embed/formik-example-nut8p?fontsize=14&hidenavigation=1&theme=dark

You can add the attribute min to your input
<input
id="rank"
placeholder="Enter your rank"
type="number"
value={values.rank}
min="1"
onChange={handleChange}
onBlur={handleBlur}
/>

Pass a validate function
// Synchronous validation
const validate = values => {
const errors = {};
if (!values.numberFied < 0) {
errors.numberFied = 'Must be positive';
}
//...
return errors;
};

Related

Why I can't fill anything in my form in React?

So I have a form, and I need users to fill this form and when they send a message, it should come to my gmail. I use EmailJS service for this.
So my form looks like this:
So as you see, users can send me messages, and my code looks like this:
Usestate for sending data:
const [toSend, setToSend] = useState({
from_name: '',
to_name: '',
message: '',
reply_to: '',
subject: ''
});
onSubmit function:
const onSubmit = (e) => {
e.preventDefault();
send(
'service_id',
'template_id',
toSend,
'user_id'
)
.then((response) => {
console.log('SUCCESS!', response.status, response.text);
})
.catch((err) => {
console.log('FAILED...', err);
});
reset();
};
handleChange function:
const handleChange = (e) => {
setToSend({ ...toSend, [e.target.name]: e.target.value });
};
useform hook:
const {register, handleSubmit, formState: { errors }, reset, trigger} = useForm();
Whole form:
<form onSubmit={handleSubmit(onSubmit)}>
<input type="text"
placeholder="Name"
name="from_name"
value={toSend.from_name}
onChange={handleChange}
id="name" {...register('name', { required: "Name is required" })}
onKeyUp={() => {
trigger("name");
}}/>
{errors.name && (<span className="danger_text">{errors.name.message}</span>)}
<input type="text"
placeholder="Email"
name="reply_to"
value={toSend.reply_to}
onChange={handleChange}
id="email" {...register("email", { required: "Email is Required" ,
pattern: {
value: /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: "Invalid email address",
}})}
onKeyUp={() => {
trigger("email");
}}
/>
{errors.email && (
<small className="danger_text">{errors.email.message}</small>
)}
<input type="text"
placeholder=
"Subject"
id="subj"
name="subject"
value={toSend.subject}
onChange={handleChange}/>
<input type="text"
placeholder="Message"
id="msg"
name="message"
value={toSend.message}
onChange={handleChange}
{...register('msg', { required: true })}/>
{errors.msg && (<small className="danger_text">Enter your message</small>)}
<input type="submit" className="btn_red" value="Send a message"></input>
</form>
So my problem is that I can't fill anything in inputs. When I try to type something it just doesn't type in, I'm guessing it has something to do with "value=.." in all inputs, but I'm not sure what's exactly the problem here.
You don't need to define onChnage, value, onKeyUp on your inputs, when you call register on input, it returns onChange,onBlur,ref, then react-hook-forms will control the values by ref. so below example should solve your problem:
import { useForm } from 'react-hook-form';
...
function MyComp() {
const {
register,
handleSubmit,
formState: { errors },
reset,
} = useForm();
const onSubmit = (toSend) => {
send(
'service_id',
'template_id',
toSend,
'user_id'
)
.then((response) => {
console.log('SUCCESS!', response.status, response.text);
})
.catch((err) => {
console.log('FAILED...', err);
});
reset();
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
type="text"
placeholder="Name"
name="from_name"
id="name"
{...register('from_name', { required: 'Name is required' })}
/>
{errors.from_name && (
<span className="danger_text">{errors.from_name.message}</span>
)}
<input
type="text"
placeholder="Email"
name="reply_to"
id="email"
{...register('reply_to', {
required: 'Email is Required',
pattern: {
value: /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address',
},
})}
/>
{errors.reply_to && (
<small className="danger_text">{errors.reply_to.message}</small>
)}
<input
type="text"
placeholder="Subject"
id="subj"
name="subject"
{...register('subject')}
/>
<input
type="text"
placeholder="Message"
id="msg"
name="message"
{...register('message', { required: true })}
/>
{errors.message && <small className="danger_text">Enter your message</small>}
<input type="submit" className="btn_red" value="Send a message"></input>
</form>
);
}
BTW, consider that register works with input's name, not id.

sweetalert pop up if passwords don't match

I want to make good pop up to my project with sweetalert when the passwords don't match:
const SignUp = ({ signUpStart, userError, resetError }) => {
const [userCredentials, setUserCredentials] = useState({
displayName: "",
email: "",
password: "",
confirmPassword: "",
});
const { displayName, email, password, confirmPassword } = userCredentials;
const handleSubmit = async (event) => {
event.preventDefault();
if (password !== confirmPassword) {
alert(`password don't match`);
return;
}
signUpStart({ displayName, email, password });
};
const handleChange = (event) => {
const { name, value } = event.target;
setUserCredentials({ ...userCredentials, [name]: value });
};
return (
<div className="signup">
<h2 className="title">I do not have a account</h2>
<span>Sign up with your email </span>
<form className="sign-up-form" onSubmit={handleSubmit}>
<Form
type="text"
name="displayName"
value={displayName}
onChange={handleChange}
label="Display Name"
required
></Form>
<Form
type="email"
name="email"
value={email}
onChange={handleChange}
label="Email"
required
></Form>
<Form
type="password"
name="password"
value={password}
onChange={handleChange}
label="Password"
required
></Form>
<Form
type="password"
name="confirmPassword"
value={confirmPassword}
onChange={handleChange}
label="Confirm Password"
required
></Form>
<CustomButton type="submit">SIGN UP</CustomButton>
</form>
{userError && userError.message ? (
<SweetAlert
show={!!userError.message}
type="warning"
title="Something went wrong"
text={userError.message}
onConfirm={() => resetError()}
/>
) : null}
</div>
);
};
EDIT: i add my whole component to the question. i deleted my mapstatetoprops and dispatch.
So i basically want to run once when i hit my submit button.
I want to make the alert in the if statement. But I think I need to refactor little. Can anyone help with this?

How to disable button on submit form in formik?

I have a form in my react component with handleSubmit. What I need to do is when I submit the form(on save click) the save button automatically should get disabled and when I get the response it automatically gets enabled.
handleSubmit = async({ company, email }, { setSubmitting, setErrors }) => {
setSubmitting(true)
const { value: { status, message } } = await this.props.createCompany({ name: company, email })
if (status) {
this.fetchCompanies()
this.closeModal()
} else {
setErrors({ email: message })
}
}
<Formik
initialValues={loginDetails}
validationSchema={loginSchema}
onSubmit={(values, formikProps) => this.handleSubmit(values, formikProps)}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting
}) => (
<form onSubmit={handleSubmit}>
<div className="col-md-12">
<div className="form-group material-textfield">
<input type="text" name="email" value={values.email} onChange={handleChange} className="form-control material-textfield-input"/>
<ErrorMessage component="span" name="email" className="invalid-feedback d-block"/>
<label className="material-textfield-label">Email<span>*</span></label>
</div>
</div>
<button type="submit" className="btn btn-dark btn-lg w-100" disabled={isSubmitting}>Save</button>
</form>
)}
</Formik>
And for this I have used setSubmitting function from formik. But it doesn't work.
Kindly help.
This should help:
const onSubmitHandler = (values, formik) => {
persistYourData(values).then(r => {
formik.setSubmitting(false);
}).catch(error => console.log(error));
}
...
<Button variant="contained" color={"primary"} onClick={pr.handleSubmit} disabled={ ((!(pr.isValid && pr.dirty)) || pr.isSubmitting) }>Submit</Button>
#You can disable the button with **formik.isSubmitting** or **formik.errors** #
<Formik
initialValues={{
email: '',
password: '',
}}
validationSchema={Yup.object({
email: Yup.string().email('Invalid email address').required('Required'),
password: Yup.string().required('Required'),
})}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
});
}}
>
{(formik) => (
<Form>
<h1>Login</h1>
<Field type='email' name='email' />
<br />
<ErrorMessage name='email' />
<br />
<Field type='password' name='password' />
<br />
<ErrorMessage name='password' />
<br />
<button disabled={formik.isSubmitting || formik.errors}>Login</button>
</Form>
)}
</Formik>

onchange in a form using formik the value of the field is not updated

I'm new to react, and I'm trying to apply validations to a form.
For some reason when adding the property:
onChange={onChange}
I want to send the values to the parent component. That's why I'm using the onchange.
Nothing I write is shown in my text fields, why does this happen?
export const Son = props => {
const { onChange } = props;
return (
<Formik
initialValues={{
fullname: "",
email: ""
}}
validationSchema={Yup.object().shape({
fullname: Yup.string()
.min(2, "Your name is too short")
.required("Please enter your full name"),
email: Yup.string()
.email("The email is incorrect")
.required("Please enter your email")
})}
onSubmit={(values, { setSubmitting }) => {
const timeOut = setTimeout(() => {
console.log(values);
setSubmitting(false);
clearTimeout(timeOut);
}, 1000);
}}
>
{({
values,
errors,
touched,
handleSubmit,
isSubmitting,
validating,
valid
}) => {
return (
<Form name="contact" method="post" onSubmit={handleSubmit}>
<label htmlFor="fullname">
Fullname
<Field
type="text"
name="fullname"
autoComplete="name"
placeholder="your fullname"
onChange={onChange}
/>
</label>
{<ErrorMessage name="fullname">{msg => <p>{msg}</p>}</ErrorMessage>}
{/*errors.fullname && touched.fullname && <p>{errors.fullname}</p>*/}
<br />
<label htmlFor="email">
Email
<Field
type="email"
name="email"
autoComplete="email"
placeholder="your email"
onChange={onChange}
/>
</label>
<ErrorMessage name="email">{msg => <p>{msg}</p>}</ErrorMessage>
<br />
<button type="submit" disabled={!valid || isSubmitting}>
{isSubmitting ? `Submiting...` : `Submit`}
</button>
</Form>
);
}}
</Formik>
);
};
this is my live code:
https://stackblitz.com/edit/react-qotvwb?file=components/son_component.js
you're not using the formik handleChange at all.
I highlighted the changes that I made in https://stackblitz.com/
and you can test this working here

How to use useState hook in formik forms

I am using formik form and to get make a modal on this form how can i use useState hook ?
FormReq = ({ values, errors, touched, handleChange, isSubmitting, handleBlur }) =>
(
<>
<div className="container">
<Modal email={values.email} password={values.password}/>
</div>
<Form>
<div className="container">
<div className="form">
<Field type="email" name="email" placeholder="Email" onChange={handleChange} onBlur={handleBlur} className="inputField"/>
<Field type="password" name="password" placeholder="Password" onChange={handleChange} className="inputField"/>
<span className="buttonsubmit">
<button disabled={isSubmitting}>Submit</button>
</span>
</div>
</div>
<div className="container errors">
{ touched.email && errors.email && <p>{errors.email}</p> }
{ touched.password && errors.password && <p>{errors.password}</p> }
</div>
</Form>
</>
)
const ContactUs = withFormik({
mapPropsToValues({ email, password}){
return{
email: email || '',
password: password || ''
}
},
validationSchema: Yup.object().shape({
email: Yup.string().email('Email not valid').required('Email is required'),
password: Yup.string().min(9, 'Password must be 9 characters or longer').required('Password is required')
}),
handleSubmit(values, { resetForm }){
console.log(values);
resetForm();
}
})(FormReq)

Resources