Formik: How to know if an input is required?

Created on 26 Jun 2018  路  10Comments  路  Source: formium/formik

I'm using the isValid to check if my input is valid with the schema that I've defined with the help of Yup. And for example the email input is required in my schema. But I'm wondering if it's possible to know from the formik props if an input is required or not in order to add a '*' after the label. Maybe something like a 'isRequired'?

Most helpful comment

The solution above is essentially hardcoding. It duplicates the definitions you're making in Yup and does not solve the problem of being able to tell if I field is conditionally required:

Consider the following yup form schema for a password field that is only required when type is PASSWORD:

  password: string()
    .when('$type', {
      is: 'PASSWORD',
      then: string().required('Please enter a password'),
      otherwise: string()
    }),

There is no way (that I see) to reuse this logic in Formik, which means you need to duplicate it somewhere. I think the way to solve this would be to provide the validation schema back to the component along with the other formik props. Then it's Yup's job to provide ways of inspecting the schema for this sort of thing, (which it may already do).

All 10 comments

I think it's a question for stackoverflow.

@jeromeraffin, I think you can do that very easily by sending props to your renderInput Component and then you can display it, for example:

<Field name="email" component={renderInput} type="text" label="Tracking ID" placeholder="Tracking ID" requiredStar />

Then in your renderInput component you can do something like this:
<label>{props.label} {props.requiredStar &&<span className="text-danger">*</span>}</label>

So, asterisk is only visible if you have provide it in your props.

I hope that would help you!

The solution above is essentially hardcoding. It duplicates the definitions you're making in Yup and does not solve the problem of being able to tell if I field is conditionally required:

Consider the following yup form schema for a password field that is only required when type is PASSWORD:

  password: string()
    .when('$type', {
      is: 'PASSWORD',
      then: string().required('Please enter a password'),
      otherwise: string()
    }),

There is no way (that I see) to reuse this logic in Formik, which means you need to duplicate it somewhere. I think the way to solve this would be to provide the validation schema back to the component along with the other formik props. Then it's Yup's job to provide ways of inspecting the schema for this sort of thing, (which it may already do).

Hi @afraser I don't really understand your approach, please can you share a code snippet.

@nero2009 I've moved on from this project but basically it's common to do this sort of thing

<InputField
  showRequiredAsterisk={field.isRequired}
  label={field.label}
  error={field.error}
  value={field.value}
  onChange={setField(field.name)}
/>

Formik abstracts away most of these props with magic around the name prop, but the important thing to note is that we want to access whether or not to pass showRequiredAsterisk, but this should be based on the validation schema for the sake of having a single source of truth regarding required fields.

Hi all, I had a similar issue and I made a function to check if a field is required:

import { getIn } from 'formik'

export const isRequiredField = ({ validationSchema }, name) =>
  !!getIn(validationSchema.describe().fields, name).tests.find(
    testName => testName === 'required'
  )

It can be used this way:

import { connect } from 'formik'
import { isRequiredField } from './utils'

const InputText = ({ formik,  ...rest}) => {
  const { handleChange, handleBlur } = formik
  const { name } = rest

  return (
    <div>
      {isRequiredField(formik, name) &&
        <strong>*</strong>
      }
      <input
        {...rest}
        type='text'
        onChange={handleChange}
        onBlur={handleBlur}
      />
    </div>
  )
}

export default connect(InputText)

It is not an elegant soution... but it works! 馃槃

DISCLAIMER: I did not test properly the code, and I'm not sure if it's a good practice to rely in yup's test name (which is "required") to check this.

I would like to hear what you think about this solution!

@d-asensio Nice. Better than having to define whether a single field is required in two places.

I've added this as a feature request: #1241

@d-asensio, the code you provided did not work for me when using when, like this:

Yup.string().when('someOtherField', {
    is: 'specialValue',
    then: Yup.string().required(),
    otherwise: Yup.string().nullable().oneOf([null, undefined], 'Null'),
});

In that case getIn(validationSchema.describe().fields, name).tests returns an empty array, when it seems like it should return a test for required. I tested it, and the required validation is in fact being applied in that case.

(I just noticed that this same comment was made by someone else over on https://github.com/jaredpalmer/formik/issues/1241)

@nbrustein I have the same issue. Did you find a fix for this?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jaredpalmer picture jaredpalmer  路  3Comments

Jucesr picture Jucesr  路  3Comments

ancashoria picture ancashoria  路  3Comments

pmonty picture pmonty  路  3Comments

sibelius picture sibelius  路  3Comments