GithubHelp home page GithubHelp logo

Comments (8)

ruscoder avatar ruscoder commented on September 27, 2024 6

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.

ju1ius avatar ju1ius commented on September 27, 2024 4

Turns out you can do both:
Edit final-form array validation 3 (array-level)
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.

mschipperheyn avatar mschipperheyn commented on September 27, 2024 4

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.

ju1ius avatar ju1ius commented on September 27, 2024 3

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.

ju1ius avatar ju1ius commented on September 27, 2024

And here's a non-working example with react-final-form:
Edit final-form array validation

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.

erikras avatar erikras commented on September 27, 2024

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.

ju1ius avatar ju1ius commented on September 27, 2024

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.

erikras avatar erikras commented on September 27, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.