Import
import { Form } from '@dnb/eufemia/extensions/forms'render(<Form.Isolation />)
Description
Form.Isolation lets you isolate parts of your form so data and validations are not shared between the Form.Handler until you want to.
It's a provider that lets you provide a schema or data very similar to what the Form.Handler component does.
Good to know
- It needs to be used inside of a
Form.Handlercomponent. - All fields inside need to validate successfully before the isolated data can be committed, just like the
Form.Handlerdoes before submitting. - Input fields are prevented from submitting the form when pressing enter. Pressing enter on input fields will commit the isolated data to the
Form.Handlercontext instead. - You can provide a
schema,dataordefaultDatalike you would do with theForm.Handler. - You can also provide
dataordefaultDatato theForm.Handlercomponent. If not given on theForm.Isolationcomponent, this will define the data that will be used for the isolated data. - Using
Form.Isolationinside of aForm.Sectionis supported. - If the user enters data without committing it to the outer context, that data will be lost when navigating to another step in the Wizard. To prevent this, you can use the
preventUncommittedChangesproperty on Form.Isolation. When enabled, it will display an error message if the user tries to proceed without committing their changes. onChangeon theForm.Handlerwill be called when the isolated data gets committed.onChangeon theForm.Isolationwill be called on every change of the isolated data. UseonCommitto get the data that gets committed.
Usage
import { Form, Field } from '@dnb/eufemia/extensions/forms'export function MyForm(props) {return (<Form.HandlerdefaultData={{ isolated: 'Isolated', regular: 'Regular' }}><Form.Isolation resetDataAfterCommit><Field.String label="Isolated" path="/isolated" /><Form.Isolation.CommitButton /></Form.Isolation><Field.String label="Regular" path="/regular" /><Form.SubmitButton /></Form.Handler>)}
TypeScript support
You can define the TypeScript type structure for your data like so:
import { Form, Field } from '@dnb/eufemia/extensions/forms'type IsolationData = {persons: Array<{ name: string }>newPerson: Array<{ name: string }>}function MyForm() {return (<Form.Isolation<IsolationData>onCommit={(data) => {data // <-- is of type IsolationData}}transformOnCommit={(isolatedData, handlerData) => {return {...handlerData,persons: [...handlerData.persons, isolatedData.newPerson],}}}>...</Form.Isolation>)}
Commit the data to the form
You can either use the Form.Isolation.CommitButton or provide a custom ref handler you can use (call) when you want to commit the data to the Form.Handler context:
import { Form, Field, JSONSchema } from '@dnb/eufemia/extensions/forms'function MyForm() {const commitHandleRef = React.useRef<() => void>()return (<Form.Handler><Form.Isolation commitHandleRef={commitHandleRef}><Field.PhoneNumber path="/phoneNumber" /><Button text="Submit" onClick={commitHandleRef.current} /></Form.Isolation></Form.Handler>)}render(<MyForm />)
Prevent the form from being submitted
To prevent the Form.Handler from being submitted when there are fields with errors inside the Isolation, you can use the bubbleValidation property.
import { Form, Field } from '@dnb/eufemia/extensions/forms'render(<Form.Handler><Form.Isolation bubbleValidation><Field.String label="Required field" path="/isolated" required /><Form.Isolation.CommitButton /></Form.Isolation></Form.Handler>,)
Schema support
You can also use a schema to define the properties of the nested fields.
Using Zod schemas
import { Form, Field, z } from '@dnb/eufemia/extensions/forms'const MySection = (props) => {return (<Form.Section {...props}><Field.PhoneNumber path="/phoneNumber" /></Form.Section>)}const schema = z.object({phoneNumber: z.string().regex(/^[0-9]{10}$/),})render(<Form.Handler><Form.Isolation schema={schema}><Field.PhoneNumber path="/phoneNumber" /></Form.Isolation></Form.Handler>,)
Using JSON Schema (Ajv)
import {Form,Field,JSONSchema,makeAjvInstance,} from '@dnb/eufemia/extensions/forms'const ajv = makeAjvInstance()const isolatedSchema: JSONSchema = {type: 'object',properties: {phoneNumber: {type: 'string',pattern: '^[0-9]{10}$',},},required: ['phoneNumber'],}render(<Form.Handler ajvInstance={ajv}><Form.Isolation schema={isolatedSchema}><Field.PhoneNumber path="/phoneNumber" /></Form.Isolation></Form.Handler>,)
Clear data from isolated fields
You can clear the isolation by calling clearData:
import { Form, Field } from '@dnb/eufemia/extensions/forms'function MyForm() {return (<Form.Handler><Form.IsolationonCommit={(data, { clearData }) => {clearData()}}><Field.String path="/isolated" /><Form.Isolation.CommitButton /></Form.Isolation></Form.Handler>)}
Reset data after commit (resetDataAfterCommit)
You can reset the isolation the user committed by using resetDataAfterCommit:
import { Form, Field } from '@dnb/eufemia/extensions/forms'function MyForm() {return (<Form.Handler><Form.Isolation resetDataAfterCommit><Field.String path="/isolated" /><Form.Isolation.CommitButton /></Form.Isolation></Form.Handler>)}
Define your own data reference (dataReference)
Technically, when you use preventUncommittedChanges or resetDataAfterCommit, the Form.Isolation will use its "initial" internal data set to create a reference. This reference is used to either compare if there is a change or to reset the data context after a commit.
But in some situations, you may need a different data set than the initial data set given at the initial render.
In order to do that you can create a dataReference and pass it to the Form.Isolation component and call refresh on it whenever you need to update it.
import { Form, Field } from '@dnb/eufemia/extensions/forms'const dataReference = Form.Isolation.createDataReference()function MyForm() {useEffect(() => {// When ever you want to refresh the "reset data"dataReference.refresh()}, [])return (<Form.Handler><Form.Isolation resetDataAfterCommit dataReference={dataReference}><Field.String path="/isolated" /><Form.Isolation.CommitButton /></Form.Isolation></Form.Handler>)}
Require the user to commit before submitting (preventUncommittedChanges)
In scenarios where you want to ensure users commit their changes before submitting or navigating to the next Wizard step, you can use the preventUncommittedChanges property. This will prevent form submission (or a step change) and prompt the user to commit any uncommitted changes first.
import { Form, Field } from '@dnb/eufemia/extensions/forms'function MyForm() {return (<Form.Handler><Form.Isolation preventUncommittedChanges resetDataAfterCommit><Field.String path="/isolated" /><Form.Isolation.CommitButton /><Form.Isolation.ResetButton showWhen="uncommittedChangeDetected" /></Form.Isolation></Form.Handler>)}
The showWhen="uncommittedChangeDetected" property ensures that the reset button is displayed only when the "prevent uncommitted changes" error is visible. This helps prevent users from resetting the form unnecessarily.