Form Engine field with useRef triggers validation on change

Hi, I tried to extend the TextLineStateless fields of the Form Engine with a React ref to handle the focus more precisely for our use case. Therefore I used a custom widget map:

export const CustomWidgetMap: WidgetMap = {
	...DefaultWidgetMap,
	TextLineStateless: (props: TextLineStatelessProps) => {
		const fieldRef = useRef<HTMLElement | null>(null);
		return <DefaultWidgetMap.TextLineStateless {...props} inputRef={ref => (fieldRef.current = ref)} />;
	}
};

Unfortunately, after I added the inputRef to the component, it seems to have side effects regarding the validation of the fields.

Without inputRef: The Form Engine checks the field value as soon as the user leaves the input (onBlur).
With inputRef: The Form Engine checks the field value as soon as there’s user input. It doesn’t matter if the ref callback is defined or undefined. It happens just by using the prop.

In my case this leads to the following problem. I have a number field with minFractionalDigits - but it gets validated when I input the first number (without a blur). So this prevents me from entering a multi-digit number all by myself. When I enter a “1” then the validation instantly changes the value to “1.00”. The same if I try to backspace the last “0” of “1.00”.

Can anyone tell me why the validation is triggered in this case? Am I missing something?

I know it’s triggered by validatePartlyWith3ValueLogic in the <model>.validation.js. But I don’t know what causes it because setting a React ref shouldn’t change the state to begin with.

Thanks in advance for any useful information!

Hi @steve-windy-mist,

first of all, thanks for trying a custom solution for your custom focus behavior needs. We have too many tickets of projects wanting their behavior to be the default :slight_smile:

Your problem is, that you set the ref just for your component. There are other components higher up that rely on it too (BufferedInput widget in your case). So if you additionally pass the ref to the callback in your props, it should work again:

<DefaultWidgetMap.TextLineStateless
	{...props}
	inputRef={ref => {
		props.inputRef?.(ref);
		fieldRef.current = ref;
	}}
/>

Great, thank you! I already tried a different approach to work with props.inputRef - but obviously the wrong one. This seems to work like a charm :slight_smile: