rjsf-team / react-jsonschema-form

A React component for building Web forms from JSON Schema.
https://rjsf-team.github.io/react-jsonschema-form/
Apache License 2.0
14.1k stars 2.18k forks source link

Metadata regarding what widget/field was rendered as part of a parameter on an onChange #4250

Closed CarlosAmaral closed 2 weeks ago

CarlosAmaral commented 2 months ago

Prerequisites

What theme are you using?

core

What is your question?

Hi,

I'd like to inquire if onChange or onBlur is there a way to understand what ui component a field was rendered by. Given at the moment my form is dispatching requests onChange but for input text for example it would be best to be dispatched onBlur. Thank you!

heath-freenome commented 2 months ago

@CarlosAmaral the onChange handler does get the id of the field being updated. Are you dealing with an issue where each keystroke is calling the onChange handler and you can't keep track of things properly? You may want to consider debouncing the onChange so that an outer event handler isn't dealing with very fast keystrokes. As for making the onChange() work with onBlur instead, you likely would have to customize the BaseInputTemplate to send an outer onChange only when onBlur is called. You can see an example of doing this in the documentation (scroll down to the override and provide the onBlur()... something like (NOTE: this is pseudocode and will likely need updating with useCallback() and all the rest):

import { BaseInputTemplateProps } from '@rjsf/utils';
import { getDefaultRegistry } from '@rjsf/core';
import { Templates } from '@rjsf/mui';

const {
  templates: { BaseInputTemplate },
} = getDefaultRegistry(); // To get templates from core
// const { BaseInputTemplate } = Templates; // To get templates from a theme do this

function MyBaseInputTemplate(props: BaseInputTemplateProps) {
  const [delayedValue, setDelayedValue] = useState(props.value);
  const { onChange } = props;
  const delayedChange = (newValue) => setDelayedValue(newValue);
  const onBlur = (id, value) => {
    onChange(delayedValue, id);
  }
  // get your custom props from where you need to
  return <BaseInputTemplate {...props} onBlur={onBlur} onChange={delayedChange} />;
}
CarlosAmaral commented 1 month ago

@heath-freenome Thank you for the answer!

I'm afraid my problem is a little bit more complex. My form is updating the local state of the form onChange but also sending debounced http requests. But not only that, the API is updating the form parameters every time a response arrives. In the case of fields like enums, I'm fine with onChange. In the case of TextField, I'd rather prefer onBlur. What I'm thinking is that I can pass a parameter on Change stating the name of the widget and that should give me enough information.

heath-freenome commented 1 month ago

You are welcome. Can we close this then?

CarlosAmaral commented 1 month ago

Yes please. Thank you.