Skip to content

Commit

Permalink
feat(forms): add transformOnCommit to Form.Isolated
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Aug 13, 2024
1 parent a16d782 commit 66731f2
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ export interface Props<Data extends JsonObject> {
* Used internally by the Form.Isolation component
*/
isolate?: boolean
/**
* Transform the data before it gets committed to the form. The first parameter is the isolated data object. The second parameter is the outer context data object (Form.Handler).
*/
transformOnCommit?: (data: Data, contextData: Data) => Data
/**
* The children of the context provider
*/
Expand Down Expand Up @@ -884,17 +888,25 @@ export default function Provider<Data extends JsonObject>(
try {
if (isolate) {
const path = props.path ?? '/'
const data =
const outerData =
props.path && pointer.has(dataNested, path)
? pointer.get(dataNested, path)
: dataNested
let isolatedData = internalDataRef.current

if (typeof props.transformOnCommit === 'function') {
isolatedData = props.transformOnCommit(
isolatedData,
outerData
)
}

// Commit the internal data to the nested context data
handlePathChangeNested?.(
path,
extendDeep({}, data, internalDataRef.current)
extendDeep({}, outerData, isolatedData)
)
result = await onCommit?.(internalDataRef.current)
result = await onCommit?.(isolatedData)
} else {
result = await onSubmit()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ export type IsolationProps<Data> = Omit<
*/
commitHandleRef?: React.MutableRefObject<() => void>

/**
* A function that will be called when the isolated context is committed.
* It will receive the data from the isolated context and the data from the outer context.
* You can use this to transform the data before it is committed.
*/
transformOnCommit?: (isolatedData: Data, handlerData: Data) => Data

/**
* Will be called when the isolated context is committed.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ export const IsolationProperties: PropertiesTableProps = {
type: 'string',
status: 'optional',
},
transformOnCommit: {
doc: 'Transform the data before it gets committed to the form. The first parameter is the isolated data object. The second parameter is the outer context data object (Form.Handler).',
type: 'function',
status: 'optional',
},
commitHandleRef: {
doc: 'Provide a ref to a function that can be called from any location to commit the data to the form.',
type: 'React.Ref',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1003,4 +1003,48 @@ describe('Form.Isolation', () => {

expect(document.querySelectorAll('.dnb-form-status')).toHaveLength(2)
})

it('should support "transformOnCommit"', async () => {
const onChange = jest.fn()

render(
<Form.Handler
data={{ existing: 'data', persons: [{ name: 'John' }] }}
onChange={onChange}
>
<Form.Isolation
transformOnCommit={(isolatedData, handlerData) => {
return {
...handlerData,
persons: [...handlerData.persons, isolatedData.newPerson],
}
}}
>
<Field.String required path="/newPerson/name" />
<Form.Isolation.CommitButton />
</Form.Isolation>
</Form.Handler>
)

const commitButton = document.querySelector('button')
const isolated = document.querySelector('input')

await userEvent.type(isolated, 'Oda')
await userEvent.click(commitButton)

expect(onChange).toHaveBeenCalledTimes(1)
expect(onChange).toHaveBeenLastCalledWith({
existing: 'data',
persons: [{ name: 'John' }, { name: 'Oda' }],
})

await userEvent.type(isolated, '{Backspace>3}Odd')
await userEvent.click(commitButton)

expect(onChange).toHaveBeenCalledTimes(2)
expect(onChange).toHaveBeenLastCalledWith({
existing: 'data',
persons: [{ name: 'John' }, { name: 'Oda' }, { name: 'Odd' }],
})
})
})

0 comments on commit 66731f2

Please sign in to comment.