diff --git a/docs/lib.md b/docs/lib.md index 7d2bcd36..cd17127d 100644 --- a/docs/lib.md +++ b/docs/lib.md @@ -20,6 +20,7 @@ This component serves as the primary entry point for drawing dynamic forms. | withoutInsertFFDebounce | `boolean` | | Flag that disables the delay before inserting data into the final-form store | | destroyOnUnregister | `boolean` | | If true, the value of a field will be destroyed when that field is unregistered. Defaults to true | | generateRandomValue | `function` | | Function that is necessary to generate a random value | +| storeSubscriber | `(storeValue: FieldValue) => void` | | Subscriber function will be called when internal store of dynamic field is changed | ### Controller diff --git a/src/lib/core/components/Form/DynamicField.tsx b/src/lib/core/components/Form/DynamicField.tsx index e35ed5f9..61a71f8c 100644 --- a/src/lib/core/components/Form/DynamicField.tsx +++ b/src/lib/core/components/Form/DynamicField.tsx @@ -34,6 +34,7 @@ export interface DynamicFieldProps { destroyOnUnregister?: boolean; mutators?: DynamicFormMutators; shared?: Record; + storeSubscriber?: (store: FieldValue) => void; __mirror?: WonderMirror; } @@ -48,12 +49,18 @@ export const DynamicField: React.FC = ({ destroyOnUnregister = true, mutators: externalMutators, shared: externalShared, + storeSubscriber, __mirror, }) => { const DynamicFormsCtx = useCreateContext(); const SearchContext = useCreateSearchContext(); const {tools, store} = useStore(name); - const watcher = useIntegrationFF(store, withoutInsertFFDebounce, destroyOnUnregister); + const watcher = useIntegrationFF({ + store, + withoutDebounce: withoutInsertFFDebounce, + destroyOnUnregister, + storeSubscriber, + }); const {mutatorsStore, mutateDFState} = useMutators(externalMutators); const {store: searchStore, setField, removeField, isHiddenField} = useSearchStore(); const shared = useFormSharedStore(externalShared); diff --git a/src/lib/core/components/Form/hooks/useIntegrationFF.tsx b/src/lib/core/components/Form/hooks/useIntegrationFF.tsx index 5007baf4..9b1c54ae 100644 --- a/src/lib/core/components/Form/hooks/useIntegrationFF.tsx +++ b/src/lib/core/components/Form/hooks/useIntegrationFF.tsx @@ -10,11 +10,19 @@ import {Field as FinalFormField, useForm} from 'react-final-form'; import type {AsyncValidateError, BaseValidateError, DynamicFieldStore, FieldValue} from '../types'; import {transformArrOut} from '../utils'; -export const useIntegrationFF = ( - store: DynamicFieldStore, - withoutDebounce?: boolean, - destroyOnUnregister?: boolean, -) => { +interface UseIntegrationFFParams { + store: DynamicFieldStore; + withoutDebounce?: boolean; + destroyOnUnregister?: boolean; + storeSubscriber?: (store: FieldValue) => void; +} + +export const useIntegrationFF = ({ + store, + withoutDebounce, + destroyOnUnregister, + storeSubscriber, +}: UseIntegrationFFParams) => { const form = useForm(); const watcher = React.useMemo(() => { @@ -52,6 +60,7 @@ export const useIntegrationFF = ( const cb = (value: FieldValue) => { if (store.name) { form.change(store.name, get(transformArrOut(value), store.name)); + storeSubscriber?.(get(value, store.name)); } }; @@ -60,7 +69,7 @@ export const useIntegrationFF = ( } return debounce(cb, 100); - }, [form.change, store.name, withoutDebounce]); + }, [form.change, store.name, withoutDebounce, storeSubscriber]); React.useEffect(() => { change(store.values);