Reputation: 25
I am new to Formik & Yup Validation. I have some fields depend on semantic-ui dropdown .When I click on a field a particular input field and a drop down will open. I cannot do the validation properly. I want when Facebook is selected these fields show validate not Instagram fields, when Instagram is selected only these fields show validation not Facebook fields.. here is the working sandbox link https://codesandbox.io/s/adoring-davinci-z4qlnw?file=/src/UserInfo.jsx My validation code is here..
export const ProfessionalValidation = yup.object().shape({
category: yup.array().required('Category Name is required').nullable(),
FBfollowers: yup.string().required('Atleast One Flatform is required').nullable(),
Instafollowers: yup.string().required('Atleast One Flatform is required').nullable(),
facebookLink: yup.string().required('This Field is required').nullable(),
platform: yup.array().required('Atleast One Flatform is required').nullable(),
})
userinfo is here
import { ProfessionalValidation } from "./Validation";
import { ErrorMessage, Formik, Form, Field } from "formik";
import {
ageGroup,
categoryOptions,
Platform,
gender,
followers,
subscribers
} from "./Data";
import { Dropdown } from "semantic-ui-react";
import "./style.css";
import "./styles.css";
const UserInfo = () => {
const [selectedOptions, setOptions] = useState([]);
const [savedata, setSaveData] = useState([]);
const defaultValue = {
category: "",
platform: "",
facebookLink: "",
InstaLink: "",
Instafollowers: "",
FBfollowers: "",
subscribers: "",
youtube: ""
};
return (
<>
<Formik
initialValues={defaultValue}
validationSchema={ProfessionalValidation}
onSubmit={handleSubmit}
>
{({ values, setFieldValue }) => (
<Form>
<section className="form-styling my-4">
<div className="container">
<div className="input-box2">
<div>
<label htmlFor="category">Category*</label>
<Field
clearable
name={`category`}
fluid
multiple
search
selection
options={categoryOptions}
component={Dropdown}
placeholder="Select Category"
onChange={(_, { value }) =>
setFieldValue("category", value)
}
/>
<span style={{ color: "red" }}>
<ErrorMessage name="category" />
</span>
</div>
<div>
<label htmlFor="platform">Platform*</label>
<Field
clearable
name={`platform`}
fluid
multiple
search
selection
options={Platform}
placeholder="Select Platform"
component={Dropdown}
onChange={(_, { value }) => {
const onDropChange = () => {
setOptions(value);
setSaveData(selectedOptions);
setFieldValue("platform", value);
};
onDropChange();
}}
//onChange= {onDropChange}
/>
<span style={{ color: "red" }}>
<ErrorMessage name="platform" />
</span>
<span className="mt-3 d-block">Select at least 1</span>
</div>
</div>
{/* all selected platform show in this div */}
<div className="platform-box">
<div>
{selectedOptions.find((word) => word === "Facebook") &&
values.platform.find((word) => word === "Facebook") ? (
<div>
<div className="platform-details">
<div>
<h5>Facebook</h5>
</div>
<div>
<Field
type="text"
name="facebookLink"
placeholder="Account Link"
//onBlur={(value) => setFieldValue("facebookLink",value.currentTarget)}
/>
<span className="text-danger">
<ErrorMessage name="facebookLink" />
</span>
</div>
<div>
<Field
className="label ui selection fluid dropdown"
clearable
name={`FBfollowers`}
fluid
search
selection
options={followers}
component={Dropdown}
placeholder="Select followers"
onChange={(_, { value }) =>
setFieldValue("FBfollowers", value)
}
/>
<span className="text-danger">
<ErrorMessage name="FBfollowers" />
</span>
</div>
</div>
<span>Verify the Followers in 2-3 Business Days</span>
</div>
) : null}
{selectedOptions.find((word) => word === "Instagram") ? (
<div>
<div className="platform-details">
<div>
<h5>Instagram</h5>
</div>
<div>
<Field
type="text"
name="InstaLink"
placeholder="Account Link"
/>
</div>
<div>
<Field
className="label ui selection fluid dropdown"
clearable
name={`Instafollowers`}
fluid
search
selection
options={followers}
component={Dropdown}
placeholder="Select followers"
onChange={(_, { value }) =>
setFieldValue("Instafollowers", value)
}
/>
<span style={{ color: "red" }}>
<ErrorMessage name="Instafollowers" />
</span>
</div>
</div>
<span>Verify the Followers in 2-3 Business Days</span>
</div>
) : null}
</div>
</div>
</div>
{/* container end */}
</section>
{/* additional info */}
<section className="additional-Info ">
<div className="container">
<div className="main-box"></div>
<div className="text-start my-5">
<button type="submit" className="border-0">
<span className="btn-form btn btn-info">Continue</span>
</button>
</div>
</div>
</section>
</Form>
)}
</Formik>
</>
);
};
export default UserInfo;
Upvotes: 1
Views: 984
Reputation: 1709
Yup
provides .when
api for mixed validation.
You can use it like below.
FBfollowers: yup
.string()
.when("platform", {
is: (val) => val?.includes("Facebook"),
then: yup.string().required("Atleast One Flatform is required"),
otherwise: yup.string()
})
.nullable(),
Since the value for platform
field is an array, I've used .includes
to check whether user has selected specific platform. If this returns true
then the field will be made mandatory, otherwise it will be non-mandatory.
Here is updated code for validation.jsx
file.
import * as yup from "yup";
export const ProfessionalValidation = yup.object().shape({
category: yup.array().required("Category Name is required").nullable(),
FBfollowers: yup
.string()
.when("platform", {
is: (val) => val?.includes("Facebook"),
then: yup.string().required("Atleast One Flatform is required"),
otherwise: yup.string()
})
.nullable(),
Instafollowers: yup
.string()
.when("platform", {
is: (val) => val?.includes("Instagram"),
then: yup.string().required("Atleast One Flatform is required"),
otherwise: yup.string()
})
.nullable(),
facebookLink: yup
.string()
.when("platform", {
is: (val) => val?.includes("Facebook"),
then: yup.string().required("This field is required"),
otherwise: yup.string()
})
.nullable(),
platform: yup.array().min(1, "Atleast one Field is required").nullable()
});
And here is the updated working code sandbox.
Here is more on the .when
api of Yup
.
Hope this helps.
Upvotes: 1