Import
import { useFieldProps } from '@dnb/eufemia/extensions/forms'// Use useFieldProps
Description
The useFieldProps hook standardize handling of the value flow for a single consumer component representing one data point. It holds error state, hides it while the field is in focus, connects to surrounding DataContext (if present) and other things that all field or value components needs to do. By implementing custom field or value components and passing the received properties through useFieldProps, all these features work the same way as other field or value components, and you only need to implement the specific unique features of that component.
How to use
import { useFieldProps } from '@dnb/eufemia/extensions/forms'const MyFieldComponent = (props) => {const { value, ...rest } = useFieldProps(props)return <Input value={value} {...rest} />}render(<MyFieldComponent path="/dataSelector" />)
Advanced usage:
import { Form, useFieldProps } from '@dnb/eufemia/extensions/forms'const MyFieldComponent = (props) => {const translations = Form.useTranslation().MyFieldconst errorMessages = React.useMemo(() => {return {// My default error messages'Field.errorRequired': translations.myErrorMessage,'MyCustom.message': translations.myCustomErrorMessage,...props.errorMessages,}}, [props.errorMessages])const preparedProps = {errorMessages,// Your component props...props,}const {// Return Parameters:value,handleChange,handleFocus,handleBlur,htmlAttributes,// Component Properties...rest} = useFieldProps(preparedProps)return (<Inputvalue={value}onChange={handleChange}onFocus={handleFocus}onBlur={handleBlur}{...htmlAttributes}{...rest}/>)}
Internal Properties
All properties are optional and can be used as needed. These properties can be provided as part of your component properties.
valuethe input value (string).emptyValuedefines what value is considered to be empty. Defaults toundefined. But an empty string is also validated when required is true.paththe JSON pointer that defines the entry name/key in the data structure.itemPathsimilar topath, but is used when run inside the Iterate context.
Validation
requiredif true, it will callvalidateRequiredfor validation.schemaorpatternfor JSON schema validation powered by ajv.onChangeValidatoryour custom validation function. It will run on every keystroke. Can be an async function. Use it together with debounceAsync.onBlurValidatoryour custom validation function. It will run on ahandleBlur()call. Use it overonChangeValidatorfor validations with side-effects. Can be an async function.validateRequireddoes allow you to provide a custom logic for how therequiredproperty should validate. See example down below.validateInitiallyin order to show an error without a change and blur event. Used for rare cases.validateUnchangedin order to validate without a change and blur event. Used for rare cases.validateContinuouslyin order to validate without a focus event beforehand. Used for rare cases.
Validators
exportValidatorsobject with your validators you want to export. More info down below.
For more advanced use cases, you can export your custom Field validators with exportValidators. They are then available (as validators in object of the second validator parameter) to be used in the validator.
When an array is returned from the validator, it will be used to only call these validators (in the order they are returned). If no array is returned, the internal validator will be called in addition.
const MyField = (props) => {const myInternalValidator = useCallback(() => {if (value === 'fail now') {return new Error('Internal validation error')}}, [])return (<Field.String exportValidators={{ myInternalValidator }} {...props} />)}const myValidator = (value, { validators: { myInternalValidator } }) => {if (value === 'fail') {return new Error('My error')}return [myInternalValidator] // optional}render(<MyField onBlurValidator={myValidator} />)
Error
errorlikenew Error()ornew FormError()that includes a message to display. More info down below.errorMessagesobject with your custom messages or translation keys, such as'Field.errorRequired'. More info down below.
Return Parameters
It returns all of the given component properties, in addition to these:
valuethe output value.idcreates a memorized id.dataContextthe internal shared data context.errorthe error object, in case an error is invoked. Will skip returning the error object, if the hook is used in a nested FieldBlock.hasErrorwill return true in case of an error, even if the hook is nested in aFieldBlock.htmlAttributesobject that include needed HTML (e.g. aria-_ or data-_) attributes, ready to be spread on form elements. It includes in addition internal aria attributes such asaria-invalid,aria-requiredandaria-describedby.isChangedreturnstrueif the value has changed with e.g.handleChange.setHasFocusaccepts a boolean as value. When called, it will update the internal logic - for event handling and validation. Will re-render the React Hook and its outer component.onFocusevent handler to assign to a form element.onBlurevent handler to assign to a form element.onChangeevent handler to assign to a form element. When anasyncfunction is used, it will set thefieldStateto pending. The corresponding FieldBlock will show an indicator on the field label.
Custom validateRequired
const validateRequired = (value, { emptyValue, required, isChanged }) => {if (required && value === emptyValue) {return new FormError('Field.errorRequired')}}const { error, hasError } = useFieldProps({value: undefined,required: true,validateInitially: true,validateRequired,errorMessages: {'Field.errorRequired': 'Show this when "required" fails.',},})
Validation order
During validation, the different APIs do have a prioritization order and will stop processing further when they match:
requiredpropertyschemaproperty (includingpattern)onChangeValidatorpropertyonBlurValidatorproperty
Error handling
Validation and error-handling are tightly coupled together. When a validation fails, you may use the error-object to handle and show the failures/statuses:
render(<Field.Stringlabel="Label"error={new Error('This is what is wrong...')}/>,)
But when you handle errors via useFieldProps, you may rather provide an object with messages, which will be used to display the error:
const { error, hasError } = useFieldProps({required: true,errorMessages: {'Field.errorRequired': 'Show this when "required" fails!',},...componentProps,})
To re-use existing errorMessages, you can use the FormError constructor as well:
import { FormError } from '@dnb/eufemia/extensions/forms'// Will show the message from the errorMessagesnew FormError('Field.errorRequired')
In order to invoke an error without a change and blur event, you can use validateInitially:
const { error, hasError } = useFieldProps({value: undefined,required: true,validateInitially: true,errorMessages: {'Field.errorRequired': 'Show this when "required" fails!',},})
Event handlers
-
handleFocus()to call theonFocusevent. -
handleBlur()to call theonBlurevent. -
handleChange(value)to call theonChangeevent. Will update/change the internal value and re-render the React Hook, so will the outer component too.
handleChange(value, (additionalArgs = null))
When additionalArgs is provided, it will be passed to the onChange, onFocus or onBlur events as the second argument. It will be merged with the internal additionalArgs, which includes props (including all of the given properties), getValueByPath and getSourceValue.
-
updateValue(value)to update/change the internal value, without calling any events. -
forceUpdate()to re-render the React Hook along with the outer component.
Value transformers
The transformers are hooks to transform the value on different stages.
They should return a transformed value: (value) => value
-
toInputtransforms the value before it is returned. This applies whether the original source of the value is the value property or the data context. -
fromInputtransforms the value given byhandleChangebefore it is used in the further process flow. Use it to destruct the value from the original event object. -
toEventtransforms the internal value before it gets returned by even callbacks such asonChange,onFocusandonBlur. The second parameter returns the event type:onChange,onFocus,onBluroronBlurValidator. -
fromExternaltransforms the providedvalueproperty before any other operations are performed. -
transformValuetransforms the value given byhandleChangeafterfromInputand beforeupdateValueandtoEvent. The second parameter returns the current value. -
provideAdditionalArgsprovide a function that can be called by the field to provide additional parameters, so events (onFocus,onBlurandonChange) and transformers (transformOut) get an additional parameter when transforming the value.
In addition there are field value transformers which should be used outside of the field component (by the field consumer):
-
transformIntransforms thevaluebefore it's displayed in the field (e.g. input). -
transformOuttransforms the value before it gets forwarded to the form data object or returned as the onChange value parameter.