Comments (16)
Yes, you can create a mapPropsToValues
function that would flatten the array and prefix/suffix each item.
const withFormik = Formik(
...
mapPropsToValues: ({id, email, pets}) => ({
id,
email,
...(pets.reduce((accum, current, index) => Object.assign(accum, {
[`pet_type_{index}`]: current.type,
[`pet_name_{index}`]: current.name,
}), {})
})
...
)
This results in props.values
that's equivalent to:
{
id: string,
email: string,
pet_type_1: string,
pet_name_1: string,
pet_type_2: string,
pet_name_2: string,
...
pet_type_n: string,
pet_name_n: string,
}
There are many ways to then display the pets. Using Object.keys
and filter
what I usually use in this situation. However, it really depends on your requirements. In the case of arbitrarily adding pets, you'll need to use props.setValues
which allows you to declaratively call setState
on just the key of Formik.state.values
. This will modify props.values
. If you need to rearrange or delete pets arbitrarily, you would not use the pets array index, but rather a uuid to uniquely identify each pet in the flattened state tree. Anyways, here's the simplest case (when the number of pets doesn't change).
// example of a form with a nested array that doesn't change size
const myForm = ({ values, handleSubmit, handleChange }) => (
<form onSubmit={handleSubmit}>
<input type="email" onChange={handleChange} id="email" />
{Object.key(values).filter(v => v.startsWith('pet')).map((pet, i) => {
<span>
<input type="text" id={`pet_type_${i}`} value={values[`pet_type_${i}`]} onChange={handleChange} />
<input type="text" id={`pet_name_${i}`} value={values[`pet_name_${i}`]} onChange={handleChange} />
</span>
})}
<button type="submit">Submit</button>
</form>
)
Hope that helps.
from formik.
@bitstrider @jaredpalmer
While you can take the above approach if you want, it's worth noting you're not required to flatten the values out. Formik will work fine with complex nested data structures within values
-- you just have to handle them in your render and handlers. Flattening is useful when using regular HTML inputs, but you can always design your own components which deal with whatever data structures you want.
What I would probably do, if your API is taking an arbitrary number of pets
, is build a controlled component called PetsInput
that takes your nested array and an value
prop, and an onChange
callback that uses the handleChangeValue
signature. You could design PetsInput
as you wish, including add/delete/reorder controls if you wanted, all contained within that reusable component.
Then from your Formik form render you would just do something like:
<label>Pets</label>
<PetsInput id="pets" value={props.values.pets} onChange={props.handleChangeValue} />
from formik.
What about arrays with useFormik?
I have already used useFormik and now kinda confused of how to make arrays of components from initialValues, the values are updating but the component doesn't.
Please help
from formik.
how would I use the handleChangeValue
to update the pet[0].name
value with the approach @eonwhite
suggested?
I can't seem to find a way to update a particular object in an array.
from formik.
Hey @davidhernon - could you please elaborate on using Yup's lazy
method in conjunction with Formik's validationSchema
to produce validation rules for dynamically added fields?
from formik.
For anyone ending up here. Formic has a <FieldArray />
component that solves this! FieldArray Docs π
from formik.
@dannief You can use Yups lazy function in order to create a schema at validation time.
Using this allowed me to add validation schema for dynamically created inputs.
from formik.
Note you would use the same .reduce
method trick to create a properly keyed validationSchema
and mapValuesToPayload
, respectively
from formik.
@bitstrider agree with @eonwhite 100%.
from formik.
@jaredpalmer @eonwhite thanks these solutions work, and perhaps should get included in the README since array of fields is a common use case for forms IMO (esp say on admin panels).
I think mapPropsToValue
and mapValuesToPayload
adds an interesting degree of freedom, but in general I would prob end up avoid having to manage multiple data shapes.
from formik.
Formik will pass all props that are not function into values automatically. If you donβt specify mapValuesToPayload, all values become payload by default. These methods are meant to help organize your code. They make refactoring much easier
from formik.
Note you would use the same .reduce method trick to create a properly keyed validationSchema and mapValuesToPayload, respectively
Am I right in assuming that if I wanted to dynamically add inputs that should be validated, then the implementation that you described would not work, since the yup schema is set within the formik config and cannot be updated dynamically?
Are there any plans to better support this scenario? I am thinking that without requiring the developer to manually flatten the values and schema, if we provide a mapping such as pets[1].type
, it could just work and easily support dynamic forms. I am currently using the form library by the author of yup called react-formal and this is the approach used. I like HOC and flexible approach of formik though and wanted to evaluate it for another project. It is not so flexible in this scenario so it's stopping me from going forward with it right now. But great job by the way.
from formik.
@davidhernon Thanks for the tip. Will check out the lazy function
from formik.
@jaredpalmer I think there could be some kind of implementations like the <Filed>
, we could add a new HoC <Fields />
to automate mapping array
to fields item_1, item_2 ...
and assembling them back to array while calling onSubmit
from formik.
For anyone ending up here. Formic has a
<FieldArray />
component that solves this! FieldArray Docs π
Field Array docs moved to https://jaredpalmer.com/formik/docs/api/fieldarray
from formik.
I used useFormik and made it work like this
schema:
[ { value: 48 }, { value: 48 } ]
`
<input
type='number'
placeholder={intl.formatMessage({ id: "APP.MODAL.FEEDBACK.INPUT.NAME" })}
autoComplete='off'
{...formik.getFieldProps(index + ".value")}
className={clsx(
'form-control bg-transparent',
{
'is-invalid': formik.touched[index]?.value && formik.errors[index]?.value,
},
{
'is-valid': formik.touched[index]?.value && !formik.errors[index]?.value,
}
)}
/>
{formik.touched[index]?.value && formik.errors[index]?.value && (
{formik.errors[index]?.value}
)}
from formik.
Related Issues (20)
- Validation Error HOT 4
- handleChange can't target state values with delimiters
- Add correct types for `Field` HOT 6
- onPaste + setFieldValue does not work as intended HOT 2
- Get validating state of individual components
- Page reloads on submit if form is inside drawer component HOT 5
- Margin not added in UI HOT 3
- Uncaught (in promise) TypeError: e2 is null [CoreValidator.ts:138:2]
- Why do I have to specify a name again when using useField's onChange function?
- Support for React Native's SyntheticEvent type
- formik file upload handling HOT 4
- Consider shipping a LICENSE file with your npm package HOT 1
- useField's onChange function should accept non-string values as args
- Formik.dirty is not reacting to nested changes HOT 1
- Docs layout is a bit broken HOT 4
- React Native form resets to initial values
- Terneries, espescially deeply nested ternaries, make code difficult to read. Please do not do this. HOT 1
- RangeError: Maximum call stack size exceeded HOT 1
- Call formik.setFieldValue() with previous value as parameter
- Formik Validation
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from formik.