react-jsonschema-form icon indicating copy to clipboard operation
react-jsonschema-form copied to clipboard

Figuring out when and where to validate my custom widget

Open vamsiampolu opened this issue 7 years ago • 2 comments

I am overriding the default Input widget using a custom widget(which is a wrapper around a custom ui library). I do not understand where the library stands on validation and would like to figure out:

  • how can I retrieve the errors in the widget:

    • rawErrors and errors are only provided to the FieldTemplate, I can probably clone all the children of FieldTemplate and pass the errors to them if it is the recommended approach.

    • I find the rawErrors is NULL even when I use liveValidate which ignores pristine state.

  • who is responsible for validating the widget when it is blurred:

    • should it rely on the Form component to provide it with onBlur or should it validate itself by implementing an onChange and onBlur as a stateful component.

    • would it be a better idea to create a HoC to determine if an error message for a widget should be displayed?

I am currently using the HoC approach to set various states such as pristine,dirty and touched for the widget using the formContext. Is there an internal mechanism for doing this which I can rely upon?

const withInputStates = () => BaseComponent => {
  return props => {
    const {id, onBlur, formContext} = props
    const {isPristine, isTouched, setTouched, setDirty} = formContext
    const onInputBlur = e => {
      formContext.lastUpdated = id
      let value = e.target.value
      // treat empty string as undefined ISSUE NO: 402
      if (value === '') {
        value = undefined
      }
      if (isPristine(id)) {
        // if the user enters a pristine field and leaves it without
        // making any changes, it is touched, this must trigger
        // validations
        if (value === undefined) {
          setTouched(id)
        } else {
          setDirty(id)
        }
      } else if (isTouched(id)) {
        // if a value has already been touched and now the user types in it
        // it is dirty
        if (value != undefined) {
          setDirty(id)
        }
      }
      // READ THE DOCS, onBlur expects to be called with id and value
      onBlur(id, value)
    }

    return <BaseComponent {...props} onBlur={onInputBlur} />
  }
}
  • what do the status and edit properties represent in onChange:

    • is it possible to access them from the widget as props instead of getting them only in onChange so that I can determine if I should pass them as a prop to the library's input component.

    • why does status always have the value of editing and editalways have the value offalse` and what are the available values for that.

  • can I manually trigger validations(based on the schema) from my widget, an example would be when it receives props (if data is autofilled or retrieved from local storage).

    • I have attempted to set up pristine, touched and dirty states using:
const formContext = {
  lastUpdated: null,
  formControlState: {},
  setTouched: function (id) {
    debugger
    this.formControlState[id] = 'touched'
  },

  setDirty: function (id) {
    debugger
    this.formControlState[id] = 'dirty'
  },

  isTouched: function (id) {
    return this.formControlState[id] === 'touched'
  },

  isPristine: function (id) {
    return this.formControlState[id] == null
  },

  isDirty: function (id) {
    return this.formControlState[id] === 'dirty'
  }
}

formContext.isPristine = formContext.isPristine.bind(formContext)
formContext.isTouched = formContext.isTouched.bind(formContext)
formContext.isDirty = formContext.isDirty.bind(formContext)
formContext.setDirty = formContext.setDirty.bind(formContext)
formContext.setTouched = formContext.setTouched.bind(formContext)

I use it with onBlur as described in the point above.

The validate is not triggered when a field is touched, it is only triggered after a field is dirty. Please take a look at it in the context of the example below. It might be important to trigger validations manually using props on either FieldTemplate or widget itself.

  • can I toggle validation on the form using uiSchema

  • disable and enable the submit button when rawErrors are detected. I notice that onSubmit prop on the form is not triggered but how can we receive it as a prop from the library.

    • onError is called when submit is clicked and a validation error occurs, I need to disable submit before error occurs
  • Implementing a custom validate function does not allow me to figure out which field is being edited at the moment. I might want to only handle custom validation for the appropriate function.

I have created an example here, I implemented a custom validate for require(I want required validation on dirty without {errors} in FieldTemplate):

  • type in username field

  • custom validation is triggered

  • all fields with required error are validated and errors are added to all of them

vamsiampolu avatar Apr 26 '17 04:04 vamsiampolu

Hi, I don't think we have good answers for any of these questions. I think one important problem is that we don't support passing error information "in" to the form (see #155). Additionally, I don't think we have a clear UX paradigm that dictates when to validate fields (see for instance #512). I agree that these are problems and I think we should address them, time permitting.

glasserc avatar Apr 18 '18 19:04 glasserc

Hi, i know its an old issue, but after spending couple of days without a hint, maybe here i will finally find an answer. How can raise an error from within a custom widget ?

i have a form with my custom widgets and also with customer-created widgets. some of those customer-created widgets may have custom validations, and i need to know how i should instruct them to raise validation errors.

snirotem avatar Dec 16 '20 21:12 snirotem