Skip to content

Commit b16552c

Browse files
committed
✨ [open-formulieren/open-forms#4699] Trigger AddressNL validation after dirty
To trigger the validation once the addressNL component has changed, we have to monitor formik changes. Using the `dirty` property from the `useFormikContext` we can simplify this monitoring. Unfortunately we can only set/alter the validation on the top level. With this we have three options: - We can add `onBlur` properties to all addressNL fields. This means that we can handle formValidation after blur, and only when `dirty === true`. This would add a lot of custom properties and logic, for a small 'problem'. This would also move us futher from a "the component functions on its own" way of working. - We can add `onBlur` eventListeners via `useEffect`. This would give us the same functionality as the previous option, without all the custom properties. It would also make the addressNL component even more complex and introduce unexpected behavior. - Finally we can change the validation rule based on the `dirty` property. For this to work, we would have to pass the `dirty` prop to the parent component, to then change the validation rule. It is a strange way to work, but would mean the least amount of custom behavior and keep the validation process understandable. For simplicity sake, I've chosen the last option. To use the `dirty` prop from the formik context to change the addressNL component validation
1 parent 74147f9 commit b16552c

File tree

1 file changed

+36
-17
lines changed

1 file changed

+36
-17
lines changed

src/formio/components/AddressNL.jsx

+36-17
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
*/
44
import {Formik, useFormikContext} from 'formik';
55
import debounce from 'lodash/debounce';
6-
import {useContext, useEffect} from 'react';
6+
import {useContext, useEffect, useState} from 'react';
77
import {createRoot} from 'react-dom/client';
88
import {Formio} from 'react-formio';
99
import {FormattedMessage, IntlProvider, defineMessages, useIntl} from 'react-intl';
1010
import {z} from 'zod';
11-
import {toFormikValidationSchema} from 'zod-formik-adapter';
11+
import {toFormikValidate} from 'zod-formik-adapter';
1212

1313
import {ConfigContext} from 'Context';
1414
import {get} from 'api';
@@ -299,6 +299,7 @@ const addressNLSchema = (required, intl, {postcode = {}, city = {}}) => {
299299

300300
const AddressNLForm = ({initialValues, required, deriveAddress, layout, setFormioValues}) => {
301301
const intl = useIntl();
302+
const [dirty, setDirty] = useState(false);
302303

303304
const {
304305
component: {
@@ -338,6 +339,13 @@ const AddressNLForm = ({initialValues, required, deriveAddress, layout, setFormi
338339
return {message: ctx.defaultError}; // use global schema as fallback
339340
};
340341

342+
const handleFormikAddressDirtyChange = newDirtyState => {
343+
// Only set the dirty state from `false` to `true`. Once it's dirty, it will remain dirty.
344+
if (!dirty && newDirtyState) {
345+
setDirty(newDirtyState);
346+
}
347+
};
348+
341349
return (
342350
<Formik
343351
initialValues={initialValues}
@@ -347,35 +355,46 @@ const AddressNLForm = ({initialValues, required, deriveAddress, layout, setFormi
347355
city: true,
348356
}}
349357
validateOnChange={false}
350-
validationSchema={toFormikValidationSchema(
351-
addressNLSchema(required, intl, {
352-
postcode: {
353-
pattern: postcodePattern,
354-
errorMessage: postcodeError,
355-
},
356-
city: {
357-
pattern: cityPattern,
358-
errorMessage: cityError,
359-
},
360-
}),
361-
{errorMap}
362-
)}
358+
validate={values =>
359+
dirty
360+
? toFormikValidate(
361+
addressNLSchema(required, intl, {
362+
postcode: {
363+
pattern: postcodePattern,
364+
errorMessage: postcodeError,
365+
},
366+
city: {
367+
pattern: cityPattern,
368+
errorMessage: cityError,
369+
},
370+
}),
371+
{errorMap}
372+
)(values)
373+
: {}
374+
}
363375
>
364376
<FormikAddress
365377
required={required}
366378
setFormioValues={setFormioValues}
367379
deriveAddress={deriveAddress}
368380
layout={layout}
381+
setDirty={handleFormikAddressDirtyChange}
369382
/>
370383
</Formik>
371384
);
372385
};
373386

374-
const FormikAddress = ({required, setFormioValues, deriveAddress, layout}) => {
375-
const {values, isValid, setFieldValue} = useFormikContext();
387+
const FormikAddress = ({required, setFormioValues, deriveAddress, layout, setDirty}) => {
388+
const {values, isValid, setFieldValue, dirty} = useFormikContext();
376389
const {baseUrl} = useContext(ConfigContext);
377390
const useColumns = layout === 'doubleColumn';
378391

392+
useEffect(() => {
393+
if (dirty) {
394+
setDirty(dirty);
395+
}
396+
}, [dirty, setDirty]);
397+
379398
useEffect(() => {
380399
// *always* synchronize the state up, since:
381400
//

0 commit comments

Comments
 (0)