Is your feature request related to a problem? Please describe.
For extra context, see #445
I'm trying to port some of my simple forms from redux-form to formik. One first issue I had was that initialValues is required.
I'm using some HOC that creates full-fledged forms from a component describe only the form fields (e.g. for a user profile: first name, last name, password, etc.). I find that it is duplicate work to define all fields in the form component, and then to redefine all those keys with an empty value (most often an empty string '') - especially since redux-form gets away without it.
Something that looks like this:
// UserProfilePage.js
import UserProfileForm from './UserProfileForm'
// ...
export default createPage({component: UserProfileForm, url: '/users/self', ... })
// UserProfileForm.js
export default const UserProfileFrom = () => (
<div>
<Field name="firstname" label="First name" />
...
</div>
);
Formik would have me do this instead:
// UserProfilePage.js
// ...
export default createPage({
component: UserProfileForm,
url: '/users/self',
initialValues: { firstname: '', lastname: '' },
// ...
});
... which is pretty redundant.
Describe the solution you'd like
I think initialValues and mapPropsToValues could be made optional, defaulting all values to an empty string ''.
On top of that, fields defined using Field could be registered so that when the form is submitted, they are marked as touched. Currently, they are not, which means that any error that is for a field that wasn't explicitly defined in initialValues or mapPropsToValues will not be shown - you can see an example here: https://codesandbox.io/s/1o7lkpmk8j
Describe alternatives you've considered
Fro the first issue (defaulting values to ''), this is what I'm doing in my form components:
// UserProfileForm.js
<Field name="firstname" component={TextField} label="First Name" />
// TextField.js
import { TextField as FTextField } from '...';
export const TextField = props => {
const { children, field, form, ...other } = props;
const newProps = {
touched: form.touched[field.name],
error: form.errors[field.name],
value: field.value || '', // defaulting to empty string to avoid disconnecting the component
name: field.name,
onChange: field.onChange,
onBlur: field.onBlur,
};
return <FTextField {...newProps} {...other} />;
};
For the second issue (auto-touching Field):
setErrors also does a pass of setFieldTouched for each of its keys.Let me know what you think!
This will now be possible thanks to #684 . We'll now be able to construct initialValues (if not specified) by looking at what fields have mounted and assuming they are just strings.
@charlax hey, this is now possible with beta 5! We should probably mark initialValues optional for Typescript users (you still have to pass at least empty object) but I am afraid people start to complain why fields are not marked as touched (when not using Field component)
@jaredpalmer what do you think?
Is there an update on this? I'm running version 1.0.1, but when I don't provide the initialValues I still get the changed an input from uncontrolled to controlled error. (I'm using the Render prop)
It would be really nice to have a default initialValues. 👍
Hola! So here's the deal, between open source and my day job and life and what not, I have a lot to manage, so I use a GitHub bot to automate a few things here and there. This particular GitHub bot is going to mark this as stale because it has not had recent activity for a while. It will be closed if no further activity occurs in a few days. Do not take this personally--seriously--this is a completely automated action. If this is a mistake, just make a comment, DM me, send a carrier pidgeon, or a smoke signal.
Still think this would be important :)
The doc says that formik touches all fields, but I am not observing this for FieldArray. Is that expected?
I'll try a PR for this sometime this week.
Any help needed here? Would be happy to have a look at this since I need it. With 1.4.0, it's still not auto-touching registered fields.
For the moment, I'm just using submitCount:
const touched = getIn(form.touched, field.name) || form.submitCount > 0;
Another issue: when submitting then resetting the form, it seems that the initialValues are not reset as well.
Is this going to be addressed? Recent activity here and in other issues/PRs doesn't say one way or the other, or is stale.
Using submitCount to delay showing validation errors whenever initialValues can't be fully provided works just fine so I don't see a pressing need to, but it does feel like a bug when you bump into this behavior. It'd definitely be much nicer if we could rely on all fields to be touched on submit.
My team is new to Formik - does this issue mean that every time we initialize a form we have to explicitly set every field in initialValues to empty?
That seems like a lot of unnecessary typing, but also does seem like the way the library is supposed to be used, if not using one the workarounds here or here.
I've been struggling to display ErrorMessages on input fields with errors upon submit, without the user touching any field.
On my project I have a bunch of forms and I'm not using the Field component, just a custom Input, so maybe if I use Field these problems won't happen - I might do that at some point. I'm also using Yup for validation.
I could go deeper investigating this but I’ve spent way too much time already, also I'm a bit exhausted. Here's the outcome of my research and how I fixed these problems:
If a form is not dirty (no fields are touched) and the user tries to submit, an ErrorMessage might not be shown. This might be because that field is not touched. So, even though it has errors, the ErrorMessage won’t be displayed because that field isn't touched. That makes sense to me, except when _no fields_ are touched, in which case all fields with errors should be “touched” by Formik so the ErrorMessages are displayed, or something like that.
It might be that the fields aren’t set to touched because they don’t have an initialValue, so always set an initial value, an empty string works. That was suggested by the author on one of these threads. I think it does that because Formik needs to know the initialValues of the field to compare with the actual values and then it knows whether the form is dirty or not, and will only set the fields to touched upon submit if the form is not dirty... maybe?
In one use case of mine, a form is rendered conditionally on a page with another form (like Step 1 and 2) - _I think_ that for this reason the initialValues didn’t work, but I might be wrong. So, even though initialValues were set, when debugging the props, initialValues would just be an empty object. And therefore, trying to submit the form without the user touching the fields wouldn't display the error messages (because Formik wouldn't set them to touched). But using enableReinitialize={true} in the Formik component fixed that - don't know why is that, any ideas?
I have the same usecase as @isaacalves - imo the error messages should be shown anyway, touched or not touched. I really don't see the point in it, to show it only when it's touched... The need to set empty defaultValues and touch every field is really cumbersome :(((((
Maybe it will help someone. I use this instead of useField.
export function useSelfRegisteredField(propsOrFieldName, initialValue = null) {
const formContext = useFormikContext();
const [field, meta] = useField(propsOrFieldName);
useEffect(() => {
if (field.value === undefined)
formContext.setFieldValue(field.name, initialValue, false);
}, []);
return [field, meta];
}
This seems to be an issue in the case of <FieldArray /> because you cannot specify the initial value for Fields that you dynamically add to the array. Is there a workaround for this?
I agree with touching all registered fields on submit and defaulting to empty string.
@jaredpalmer I add fields to my form when the user fills it out, depending on what s/he selects. The fields which are added are not marked as touched when the user submits the form; thus no error messages are displayed. Is there a way to get around this? To specify: What I want is to mark all visible fields as touched when the user submits the form.
Adding those fields to initialValues works, but then they are marked as touched although they were not rendered / visible initially.
Correct this is why this change is necessary
also not submit that value to thought backend.
Any update for this?
Thanks in advance
Any progress on this? or #683 ?
Just ran into this and since I've been using useField I did something a little different
import { useField as formikUseField, useFormikContext } from 'formik'
function useField(props) {
const fieldProps = formikUseField(props);
const form = useFormikContext();
fieldProps[1].touched = fieldProps[1].touched || form.submitCount > 0;
return fieldProps;
}
@jaredpalmer Is anyone working on this? If not I don't mind giving it a shot, if you could point me in the right direction!
I am wondering too!
The problem with touching an item in a FieldArray based on submitCount is that a newly added item just after one submit will be automatically touched, and thus the validation errors will be visible which I think is not the desired behavior.
Most helpful comment
Still think this would be important :)