-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow Fields To Access Their Requiredness #1241
Comments
Just in case anyone else comes here and needs a practical example, as @Undistraction describes above, you can read straight from the Yup.js schema to determine if a field has been marked as
|
@adaam2 Yep. That's what I don't like about this approach. You need to pass the schema around which feels clumsy. I've ended up parsing all the fields in the schema and passing down a
|
Related to #343 |
Not sure I love coupling formik to Yup even more tbh or having different behavior with/without Yup. Also FWIW you can implement this on your own if you build your own |
That brings up the question about validationSchema.. aside from yup.js, what other libraries of a similiar ilk expose a comparable interface in terms of schema? If none, then I would think that the coupling of yup and formik should be removed completely or extracted to a separate package. |
I agree with this 100%. We can get there in v3 and warn when using validationSchema in v2. However part of Formik’s success is the convenience of Yup so we def need a separate package with all of not even more yup related enhancements. |
While this is a decent solution, it doesn't work for me when using custom validation logic such as
The |
Building on what @jaredpalmer suggests, here is a
|
I tried @shotokai's solution, unfortunately it didn't work with schemas using const EnhancedField = (
props: { formik: FormikConfig<any> & FormikProps<any> } & { name: string },
) => {
const { formik, name } = props;
const validationSchema = formik.validationSchema;
const fieldValidationSchema = validationSchema
? reach(validationSchema, name, formik.values, formik.values)
: false;
const resolvedSchema = fieldValidationSchema
? fieldValidationSchema.resolve({ value: formik.values })
: false;
const tests = resolvedSchema ? resolvedSchema.describe().tests : false;
const isRequired = tests ? !!tests.find((test: any) => test.name === 'required') : false;
const enhancedProps = { ...props };
return <FormikField required={isRequired} {...enhancedProps} />;
}; |
@joefiorini what's |
Just going to throw my $0.00 in, I think ideally we'd be able to standardize the use of schemas, but not be bound to any specific framework. Then we could do Some other projects involving schemas: Schema based forms: https://react-jsonschema-form.readthedocs.io/en/latest/ |
It's a function exported from Yup import { reach } from 'yup'; |
Any other way to implement this? Seems like this doesn't work anymore (if using |
Is it just me or is validationSchema no longer available on formik prop when connect()? @jaredpalmer I understand the feel to not couple to yup, it would be great to have a simple approach we can implement ourselves that is realiable and doesn't hack internals/uses things it shouldn't Would love everyone's thoughts now as a bit of time has passed |
May have come up with a good pattern:
And in your field
|
That's a good pattern! My current thoughts are of a similar pattern, but where Formik manages the validation context. Based loosely off of this, we'd abstract the connection between Formik and Yup with a connector. const MyForm = () => {
const validator = useYupFormikValidator(yupSchema);
return (
<Formik validator={validator} validate={() => { /** additional validation **/ }}>
<MyField name="firstName" />
</Formik>
);
}
const MyField = () => {
const yup = useYupFormikContext();
return null;
} One comment with the above code @Dashue, you should wrap const { schema } = useContext(Context);
const isRequired = React.useCallback((name: string) => {
// etc
return fieldIsRequired;
}, [schema]); |
@johnrom Thanks! Updated code
|
Hey, @Dashue thanks for sharing your solution. I have one question though: schema.js: export default {
Type1: [step1Schema, step2Schema],
Type2: [step1Schema]
}; Form.jsx: return (
<Formik
initialValues={getInitialFormValues()}
validationSchema={validationSchema[type][step]}
>
{() => (
<Form>
<ValidationSchemaProvider
schema={validationSchema[type][step]}>
// ... the form steps
</ValidationSchemaProvider>
</Form>
)}
</Formik> When I call |
@tdranv Without knowing your full case, my approach to multistep would be to have different forms per step, or introduce conditional validation logic with yup. I'm assuming form validation schema wasn't built to handle being switched like that |
There are a few different schemas, exported as an array and on every step, I am switching the schema. The weird part is that it renders 3 times, 2 of which it has What did you mean by Thanks for answering :) |
In this case I'm not sure if it's possible. This link kind of shows some examples of doing it. A good way of explaining the functionality is "how do I set the global theme from a child" the theme provider sits at the top of the app and takes a toggleTheme function, this toggleTheme is then provided to the child, either through useContext, or by passing it down as props. The child calls toggleTheme and the theme changes within the provider. So you want the ValidationSchemaProvider to take schema and setSchema, but I've never done this with yup or formik, it's a simpler scenario when changing the theme or logged in user etc. Perhaps another angle to work is figuring out why it renders 3 times, if that's not expected? |
False alarm... I had a key in the schema that was just |
Good you found the issue! |
@samueldepooter I have the same issue. Did you find any solution for this? |
+1 Completely agree this should be a feature & that the workaround feel unclean |
Inspired by @todor-a, this was my solution import { Formik, FormikValues } from "formik";
import { createContext, useContext } from "react";
import { ObjectSchema } from "yup";
const SchemaContext = createContext<ObjectSchema<any> | undefined>(undefined);
export function FormikWithSchema<T extends FormikValues = FormikValues>(
props: Parameters<typeof Formik<T>>[0],
) {
return (
<SchemaContext.Provider value={props.validationSchema}>
<Formik {...props} />
</SchemaContext.Provider>
);
}
export const useSchemaContext = () => useContext(SchemaContext); Then in my field components function FormikTextField<F extends object, K extends keyof F = keyof F>(props: FormikTextFieldProps<F, K>) {
const formik = useFormikContext<F>();
const key = props.field as string;
const fieldMeta = formik.getFieldMeta(key);
const schema = useSchemaContext();
// @ts-ignore
const schemaIsNumber = schema?.fields?.[key]?.type === "number";
// @ts-ignore
const schemaIsRequired = schema?.fields?.[key]?.spec.optional === false;
// @ts-ignore
const schemaLabel = schema?.fields?.[key]?.spec.label;
const safeLabel = label || schemaLabel || "Missing Label";
const FormikProps = formik.getFieldProps(key);
return (...) Haven't fully looked into how to type the stuff coming from yup |
🚀 Feature request
If I define a Yup schema, I would expect to be able to use the information I define there to render my fields. For example if I mark a field as 'Required' in the schema I would expect to be able to find that field's requiredness within the field / input components
Current Behavior
Currently this information is only available by pulling the information from the schema manually, either doing this for all fields at the form level, or by passing the schema down and doing it on a per-component level.
Desired Behavior
This information should be made available to form and fields in an easy-to-use form.
Suggested Solution
Add another prop object which is passed down to the form rendered by Formik:
Who does this impact? Who is this for?
This would help anyone wanting to style or add elements to a field / field group based on the schema.
Describe alternatives you've considered
There is a manual alternative outlined in #712 but it really feels like this should be provided by Formik.
Another alternative would be to pass the schema down to the rendered form.
The text was updated successfully, but these errors were encountered: