In react standalone jsonforms required field validation does not get triggered for empty strings and asigning undefined results in react warning for changing controlled to uncontrolled component

Problem: In my react standalone jsonforms application, I have a required field with string type. When once field is filled up and then cleared up, the required error message is not shown. It needs to be set as undefined for error to be triggered for this field. But changing value from string to undefined or vice versa, it results in react warning saying ‘A component is changing an uncontrolled input to be controlled’, as shown in below screenshot too.
Question: Is there a solution to trigger required property error with empty string and arrays?

Hi @manju2791, this doesn’t look like a validation problem to me. I see that you use a custom text renderer. From the error message I’m assuming that you hand over the data prop directly to the text input. Many React components, including the ones from Material UI, distinguish between controlled and uncontrolled mode by checking their “value” prop. In case it’s undefined they use uncontrolled mode.

Therefore you should be able to fix this by handing over data ?? '' to your TextField. Then it’s always in controlled mode. This has no effect on the validation because the data will still be undefined.

@sdirix I have the same problem, I have created a custom text control. I am using the text control as follows

<input
          type='text'
          value={data}
          className={getClass()}
          id={id}
          onChange={(ev: any) => {
            let value = ev.target.value
            if (!value) {
              value = undefined
            }
            handleChange(path, value)
          }}
          onBlur={() => {
            validate()
          }}
        />

If I try to pass value={data ?? ‘’} as you mentioned, it doesn’t work. When the user types something and removes it again, validation is not triggered since an empty string is a valid case.

Hi @pankaj-z, the code looks correct to me.

Note that passing value={data ?? ''} has nothing to do with the validation. The validation is determined via the actual data, not what is handed over to some input. So if it doesn’t work for you it looks like the handleChange does something wrong. However it looks fine to me here so I’m wondering what the problem is.

Can you post the schema you are using as well as the whole data object when the user types something and the whole data object when the user removes the input again?

@sdirix thanks for the reply. My use case is there are multiple forms. There is continue button for each form. Once the continue button is clicked and if there are no required field errors in current form, the next form will be rendered. I have custom text renderer. If user clicks on continue button without entering any data then required validation will be triggered for the text field as expected. But when user changes a text field with some data and remove the data in text field completely then the data in the text field would be an empty string. As per my understanding ajv required field errors are not triggered for the empty string.

I have lot of fields in schema which are conditionally required. We are only using required in the schema and minLength is not provided for the required string fields.
Your thoughts?

Hi @pankaj-z, your use case makes a lot of sense. I think your approach is fine and additional validations like minLength are not needed.

For JSON Forms 3.0 we changed the default behavior. Text inputs no longer store an empty string when the user removes all input, so just by updating to JSON Forms 3.0 this should work out of the box for you.

However the custom renderer you posted should also work as you specifically make sure that the value is undefined when handing it over to handleChange. So using the custom renderer should also not store the empty string in the data. If still an empty string is stored then there must be some problem somewhere. Maybe it was registered incorrectly so that it is not even used?

Hi @sdirix Thanks for the quick reply. Actually, there is no empty string stored if I use it follows

onChange={(ev: any) => {
            let value = ev.target.value
            **if (!value) {**
**              value = undefined**
**            }**
            handleChange(path, value)
          }}

But the problem is, react now complains for the state change from controlled to uncontrolled since I am setting undefined as value.

Hi @pankaj-z,

I don’t fully understand the problem. When React complains because of the state change from controlled to uncontrolled then the previous suggestion of using value = { data ?? '' } was not followed. You must make sure that the value handed over to the React component is never undefined as this will trigger this error.