Comments (8)
I encountered the same problem with Cannot set a numeric property on an object
using JSON schema validation for the form with array fields. Any progress on this?
from final-form.
Turns out you can do both:
The trick is to use an object instead of an array:
const validateOffers = (values, form) => {
const errors = values.reduce((errors, value, i) => {
if (offerRequiresUrl(value) && !value.url) {
errors[i] = { url: 'This type of offer requires an URL' }
}
return errors
}, {})
if (!values || !values.length || !values.some(isPrimaryOffer)) {
errors[FORM_ERROR] = 'Please provide at least one primary offer'
}
return errors
}
What you can't do ATM is mixing array-level and field-level validation, because Tools.setIn
refuses to set numeric properties on an object.
The following will throw Error: Cannot set a numeric property on an object
const validateOffers = (values, form) => {
if (!values || !values.length || !values.some(isPrimaryOffer)) {
return { [FORM_ERROR] = 'Please provide at least one primary offer' }
}
}
const validateSomeOfferField = value => 'Some Error'
The following won't work because field-level validation will overwrite the whole array:
const validateOffers = (values, form) => {
const errors = []
if (!values || !values.length || !values.some(isPrimaryOffer)) {
errors[FORM_ERROR] = 'Please provide at least one primary offer'
}
return errors
}
const validateSomeOfferField = value => 'Some Error'
from final-form.
I'm using yup
for validation and I'm running into this issue:
selections: array()
.of(string().required(required))
.min(5, min)
.max(5, max),
When the array doesn't have exactly 5 items, I get this error:
final-form.es.js:117 Uncaught (in promise) Error: Cannot set a numeric property on an object
at setInRecursor (final-form.es.js:117)
at setInRecursor (final-form.es.js:68)
at setIn (final-form.es.js:140)
at final-form.es.js:634
at final-form.es.js:628
at Array.forEach (<anonymous>)
at forEachError (final-form.es.js:620)
at processErrors (final-form.es.js:633)
at afterPromises (final-form.es.js:665)
The above shows a work around, which is ok. But this is quite a common scenario. And especially with a lib like yup
which does schema validation, it's a bit of a hassle.
It should not require a workaround imho. It should allow you set an error on the array as a whole, that ideally would be available on the meta.error.selections
key. Since that's an array of items, I can see how that would not be in line with the current structure
from final-form.
It would need some additional meta information...
Would you consider adding an additional parameter to the validate function ?
Something like:
interface FieldValidationContext {
// At least this field for now
readonly fieldName: string
// Maybe this one, don't know if it's possible ATM...
readonly parentFieldName?: string
}
type Validator = (
fieldValue: any,
formValues: object,
validationContext: FieldValidationContext
) => string | undefined
from final-form.
And here's a non-working example with react-final-form:
I sort of got it to work by currying the validateOfferUrl
function, but the behavior is kind of weird... 😕
First, the meta.error
render prop of the FieldArray, which according to the docs should to be a string
or undefined
can now be an array...
Furthermore, changing the type of the first offer triggers: Error: Cannot set a numeric property on an object
... When removing the validate
prop on either the FieldArray or the Field, the error is not triggered.
from final-form.
Well, this could be done with record-level validation, but you're right, it's not entirely possible with field-level validation at the moment. It would need some additional meta information...
OR, you could do array-level validation, and provide the validate
prop to FieldArray
. That's probably your best solution for now.
from final-form.
OR, you could do array-level validation, and provide the validate prop to FieldArray. That's probably your best solution for now.
Thanks for your answer @erikras.
Running field-level validation at the array-level does work, but then we loose the ability to show errors related to the collection as a whole (like its minimun and maximum length, etc)...
See: https://codesandbox.io/s/p3jyy9767
from final-form.
Running field-level validation at the array-level does work, but then we loose the ability to show errors related to the collection as a whole (like its minimun and maximum length, etc)...
That is true. But you could do either one or the other. e.g.
const validateOffers = (values, form) => {
const errors = []
if(values.length < 4) { // 👈
return 'Need more offers' // 👈
} // 👈
values.forEach(value => {
let error = null
if (value.type === 'presale' && !value.url) {
error = { url: 'This type of offer requires an URL' }
}
errors.push(error)
})
return errors
}
Great looking form, btw.
from final-form.
Related Issues (20)
- initialValue overrides state on update HOT 1
- How to unregisterField, or at least update the registration? HOT 2
- [Feature Request] Get last dirty state of unregistered field (when `destroyOnUnregister` is false) HOT 2
- Migrate to TypeScript
- keepDirtyOnReinitialize can't handle undefined value HOT 2
- Confusing documentation/messaging
- final-form ^4.20.3 introduced a breaking change for array field names (e.g. choices[]), which worked in v4.20.2 HOT 1
- Field subscription `modifiedSinceLastSubmit`, is defined as `false`, rather than `boolean`. HOT 2
- Issue on TypeScript FieldSubscription
- form state becomes dirty when initial value is empty, and user interacting without actually changing the value HOT 1
- Reacting to onSubmit Promise rejection HOT 1
- focus/change/blur is not a function HOT 5
- Feature: Reuse field states from already created instance HOT 5
- FormSpy components are rendering sooner than previously expected
- FieldArray record level async validation not working HOT 1
- Error with validation when registering array field and array item fields together HOT 1
- Usage of keyof in TypeScript types does not align with field names
- [RFC] TypeScript rewrite of a few Final Form packages HOT 2
- Form not dirty after removing items from FieldArray using final-form-arrays
- Can't register field named 'constructor' HOT 1
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 final-form.