diff --git a/src/formio/components/AddressNL.js b/src/formio/components/AddressNL.js
index f9df85b93..fae0148e9 100644
--- a/src/formio/components/AddressNL.js
+++ b/src/formio/components/AddressNL.js
@@ -6,7 +6,7 @@ import debounce from 'lodash/debounce';
import React, {useEffect} from 'react';
import {createRoot} from 'react-dom/client';
import {Formio} from 'react-formio';
-import {FormattedMessage, IntlProvider, createIntl} from 'react-intl';
+import {FormattedMessage, IntlProvider, defineMessages, useIntl} from 'react-intl';
import {z} from 'zod';
import {toFormikValidationSchema} from 'zod-formik-adapter';
@@ -136,7 +136,6 @@ export default class AddressNL extends Field {
renderReact() {
const required = this.component?.validate?.required || false;
- const intl = createIntl(this.options.intl);
const initialValues = {...this.emptyValue, ...this.dataValue};
this.reactRoot.render(
@@ -147,16 +146,11 @@ export default class AddressNL extends Field {
requiredFieldsWithAsterisk: this.options.evalContext.requiredFieldsWithAsterisk,
}}
>
-
-
-
+ required={required}
+ setFormioValues={this.onFormikChange.bind(this)}
+ />
);
@@ -170,6 +164,17 @@ export default class AddressNL extends Field {
}
}
+const FIELD_LABELS = defineMessages({
+ postcode: {
+ description: 'Label for addressNL postcode input',
+ defaultMessage: 'Postcode',
+ },
+ houseNumber: {
+ description: 'Label for addressNL houseNumber input',
+ defaultMessage: 'House number',
+ },
+});
+
const addressNLSchema = (required, intl) => {
let postcodeSchema = z.string().regex(/^[1-9][0-9]{3} ?(?!sa|sd|ss|SA|SD|SS)[a-zA-Z]{2}$/);
let houseNumberSchema = z.string().regex(/^\d{1,5}$/);
@@ -197,7 +202,7 @@ const addressNLSchema = (required, intl) => {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: intl.formatMessage({
- descripion:
+ description:
'ZOD error message when AddressNL postcode is provided but not houseNumber',
defaultMessage: 'You must provide a house number.',
}),
@@ -209,7 +214,7 @@ const addressNLSchema = (required, intl) => {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: intl.formatMessage({
- descripion:
+ description:
'ZOD error message when AddressNL houseNumber is provided but not postcode',
defaultMessage: 'You must provide a postcode.',
}),
@@ -220,6 +225,45 @@ const addressNLSchema = (required, intl) => {
});
};
+const AddressNLForm = ({initialValues, required, setFormioValues}) => {
+ const intl = useIntl();
+
+ const errorMap = (issue, ctx) => {
+ switch (issue.code) {
+ case z.ZodIssueCode.invalid_type: {
+ if (issue.received === z.ZodParsedType.undefined) {
+ const fieldName = issue.path.join('.');
+ const fieldLabel = intl.formatMessage(FIELD_LABELS[fieldName]);
+ const message = intl.formatMessage(
+ {
+ description: 'Required field error message',
+ defaultMessage: '{field} is required.',
+ },
+ {
+ field: fieldLabel,
+ }
+ );
+ return {message};
+ }
+ }
+ }
+ return {message: ctx.defaultError}; // use global schema as fallback
+ };
+
+ return (
+
+
+
+ );
+};
+
const FormikAddress = ({required, setFormioValues}) => {
const {values, isValid} = useFormikContext();
@@ -242,12 +286,7 @@ const FormikAddress = ({required, setFormioValues}) => {
- }
+ label={}
placeholder="123"
isRequired={required}
/>
@@ -299,12 +338,7 @@ const PostCodeField = ({required}) => {
return (
- }
+ label={}
placeholder="1234 AB"
isRequired={required}
onBlur={onBlur}
diff --git a/src/formio/components/AddressNL.stories.js b/src/formio/components/AddressNL.stories.js
index cd5ce2107..6001f6b68 100644
--- a/src/formio/components/AddressNL.stories.js
+++ b/src/formio/components/AddressNL.stories.js
@@ -41,13 +41,13 @@ export const ClientSideValidation = {
const canvas = within(canvasElement);
const postcodeInput = await canvas.findByLabelText('Postcode');
- const houseNumberInput = await canvas.findByLabelText('Huis nummer');
- const houseLetter = await canvas.findByLabelText('Huis letter');
- const houseNumberAddition = await canvas.findByLabelText('Huis nummer toevoeging');
+ const houseNumberInput = await canvas.findByLabelText('Huisnummer');
+ const houseLetter = await canvas.findByLabelText('Huisletter');
+ const houseNumberAddition = await canvas.findByLabelText('Huisnummertoevoeging');
await step('Fill only postcode - client side validation error', async () => {
userEvent.type(postcodeInput, '1234AB');
- expect(await canvas.findByText('Required')).toBeVisible();
+ expect(await canvas.findByText('Huisnummer is verplicht.')).toBeVisible();
});
await step('Fill house number field', async () => {
@@ -61,13 +61,13 @@ export const ClientSideValidation = {
await waitFor(() => {
expect(houseNumberAddition).not.toHaveFocus();
- expect(canvas.queryByText('Required')).not.toBeInTheDocument();
+ expect(canvas.queryByText('/is verplicht/')).not.toBeInTheDocument();
});
});
await step('Clear postcode field, keep house number field', async () => {
userEvent.clear(postcodeInput);
- expect(await canvas.findByText('Required')).toBeVisible();
+ expect(await canvas.findByText('Postcode is verplicht.')).toBeVisible();
});
},
};
@@ -85,17 +85,17 @@ export const NotRequired = {
const canvas = within(canvasElement);
const postcodeInput = await canvas.findByLabelText('Postcode');
- const houseNumberInput = await canvas.findByLabelText('Huis nummer');
+ const houseNumberInput = await canvas.findByLabelText('Huisnummer');
await step('Enter only postcode, without house number', async () => {
userEvent.type(postcodeInput, '1234AB');
- expect(await canvas.findByText('You must provide a house number.')).toBeVisible();
+ expect(await canvas.findByText('Huisnummer is verplicht.')).toBeVisible();
});
await step('Enter only house number, without postcode', async () => {
userEvent.clear(postcodeInput);
userEvent.type(houseNumberInput, '1');
- expect(await canvas.findByText('You must provide a postcode.')).toBeVisible();
+ expect(await canvas.findByText('Postcode is verplicht.')).toBeVisible();
});
},
};
@@ -126,7 +126,7 @@ export const WithPassingBRKValidation = {
const postcodeInput = await canvas.findByLabelText('Postcode');
userEvent.type(postcodeInput, '1234AB');
- const houseNumberInput = await canvas.findByLabelText('Huis nummer');
+ const houseNumberInput = await canvas.findByLabelText('Huisnummer');
userEvent.type(houseNumberInput, '1');
// this assertion is not worth much due to the async nature of the validators...
@@ -166,7 +166,7 @@ export const WithFailedBRKValidation = {
// expect(postcodeInput).toHaveDisplayValue('1234AB');
// });
- // const houseNumberInput = await canvas.findByLabelText('Huis nummer');
+ // const houseNumberInput = await canvas.findByLabelText('Huisnummer');
// userEvent.type(houseNumberInput, '1');
// await waitFor(() => {
// expect(houseNumberInput).toHaveDisplayValue('1');
diff --git a/src/i18n/compiled/en.json b/src/i18n/compiled/en.json
index 4202b5686..4c78bd5bd 100644
--- a/src/i18n/compiled/en.json
+++ b/src/i18n/compiled/en.json
@@ -285,6 +285,16 @@
"value": "Please accept the privacy policy before submitting"
}
],
+ "8cxbC6": [
+ {
+ "type": 1,
+ "value": "field"
+ },
+ {
+ "type": 0,
+ "value": " is required."
+ }
+ ],
"8uBESg": [
{
"type": 0,
@@ -487,6 +497,12 @@
"value": "Contact details"
}
],
+ "GbPef0": [
+ {
+ "type": 0,
+ "value": "You must provide a house number."
+ }
+ ],
"GiRKAS": [
{
"type": 0,
@@ -1193,12 +1209,6 @@
"value": "House letter"
}
],
- "cHn60V": [
- {
- "type": 0,
- "value": "You must provide a house number."
- }
- ],
"cKFCTI": [
{
"type": 0,
@@ -1487,6 +1497,12 @@
"value": "Product"
}
],
+ "lKBAu3": [
+ {
+ "type": 0,
+ "value": "You must provide a postcode."
+ }
+ ],
"lVNV/d": [
{
"type": 0,
@@ -1619,12 +1635,6 @@
"value": "Use ⌘ + scroll to zoom the map"
}
],
- "p+11YF": [
- {
- "type": 0,
- "value": "You must provide a postcode."
- }
- ],
"pguTkQ": [
{
"type": 0,
diff --git a/src/i18n/compiled/nl.json b/src/i18n/compiled/nl.json
index 213aa08d2..e3d0eabe7 100644
--- a/src/i18n/compiled/nl.json
+++ b/src/i18n/compiled/nl.json
@@ -285,6 +285,16 @@
"value": "U moet akkoord gaan met het privacybeleid om door te gaan"
}
],
+ "8cxbC6": [
+ {
+ "type": 1,
+ "value": "field"
+ },
+ {
+ "type": 0,
+ "value": " is verplicht."
+ }
+ ],
"8uBESg": [
{
"type": 0,
@@ -487,6 +497,12 @@
"value": "Contactgegevens"
}
],
+ "GbPef0": [
+ {
+ "type": 0,
+ "value": "Huisnummer is verplicht."
+ }
+ ],
"GiRKAS": [
{
"type": 0,
@@ -814,7 +830,7 @@
"PCv4sQ": [
{
"type": 0,
- "value": "Huis nummer"
+ "value": "Huisnummer"
}
],
"PjYrw0": [
@@ -1194,13 +1210,7 @@
"cBsrax": [
{
"type": 0,
- "value": "Huis letter"
- }
- ],
- "cHn60V": [
- {
- "type": 0,
- "value": "You must provide a house number."
+ "value": "Huisletter"
}
],
"cKFCTI": [
@@ -1491,10 +1501,16 @@
"value": "Product"
}
],
+ "lKBAu3": [
+ {
+ "type": 0,
+ "value": "Postcode is verplicht."
+ }
+ ],
"lVNV/d": [
{
"type": 0,
- "value": "Huis nummer toevoeging"
+ "value": "Huisnummertoevoeging"
}
],
"lY+Mza": [
@@ -1623,12 +1639,6 @@
"value": "Gebruik ⌘ + scroll om te zoomen in de kaart"
}
],
- "p+11YF": [
- {
- "type": 0,
- "value": "You must provide a postcode."
- }
- ],
"pguTkQ": [
{
"type": 0,
diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json
index 19bdcc119..6c8a778a0 100644
--- a/src/i18n/messages/en.json
+++ b/src/i18n/messages/en.json
@@ -114,6 +114,11 @@
"description": "Warning privacy policy not checked when submitting",
"originalDefault": "Please accept the privacy policy before submitting"
},
+ "8cxbC6": {
+ "defaultMessage": "{field} is required.",
+ "description": "Required field error message",
+ "originalDefault": "{field} is required."
+ },
"8uBESg": {
"defaultMessage": "Invalid input: must include \"{includes}\".",
"description": "ZOD 'invalid_string' error message, with required include",
@@ -249,6 +254,11 @@
"description": "Appointments navbar title for 'contact details' step",
"originalDefault": "Contact details"
},
+ "GbPef0": {
+ "defaultMessage": "You must provide a house number.",
+ "description": "ZOD error message when AddressNL postcode is provided but not houseNumber",
+ "originalDefault": "You must provide a house number."
+ },
"GiRKAS": {
"defaultMessage": "Back to products",
"description": "Appointments location and time step: previous step text",
@@ -559,10 +569,6 @@
"description": "Label for addressNL houseLetter input",
"originalDefault": "House letter"
},
- "cHn60V": {
- "defaultMessage": "You must provide a house number.",
- "originalDefault": "You must provide a house number."
- },
"cKFCTI": {
"defaultMessage": "Add another",
"description": "Edit grid add button, default label text",
@@ -713,6 +719,11 @@
"description": "Appoinments: product select label",
"originalDefault": "Product"
},
+ "lKBAu3": {
+ "defaultMessage": "You must provide a postcode.",
+ "description": "ZOD error message when AddressNL houseNumber is provided but not postcode",
+ "originalDefault": "You must provide a postcode."
+ },
"lVNV/d": {
"defaultMessage": "House number addition",
"description": "Label for addressNL houseNumberAddition input",
@@ -773,10 +784,6 @@
"description": "Gesturehandeling mac scroll message.",
"originalDefault": "Use ⌘ + scroll to zoom the map"
},
- "p+11YF": {
- "defaultMessage": "You must provide a postcode.",
- "originalDefault": "You must provide a postcode."
- },
"pguTkQ": {
"defaultMessage": "Intersection results could not be merged",
"description": "ZOD 'invalid_intersection_types' error message",
diff --git a/src/i18n/messages/nl.json b/src/i18n/messages/nl.json
index 520b9afda..cfec7234c 100644
--- a/src/i18n/messages/nl.json
+++ b/src/i18n/messages/nl.json
@@ -115,6 +115,11 @@
"description": "Warning privacy policy not checked when submitting",
"originalDefault": "Please accept the privacy policy before submitting"
},
+ "8cxbC6": {
+ "defaultMessage": "{field} is verplicht.",
+ "description": "Required field error message",
+ "originalDefault": "{field} is required."
+ },
"8uBESg": {
"defaultMessage": "\"{includes}\" moet in de waarde zitten.",
"description": "ZOD 'invalid_string' error message, with required include",
@@ -252,6 +257,11 @@
"description": "Appointments navbar title for 'contact details' step",
"originalDefault": "Contact details"
},
+ "GbPef0": {
+ "defaultMessage": "Huisnummer is verplicht.",
+ "description": "ZOD error message when AddressNL postcode is provided but not houseNumber",
+ "originalDefault": "You must provide a house number."
+ },
"GiRKAS": {
"defaultMessage": "Terug naar producten",
"description": "Appointments location and time step: previous step text",
@@ -385,7 +395,7 @@
"originalDefault": "Payment is required for this product"
},
"PCv4sQ": {
- "defaultMessage": "Huis nummer",
+ "defaultMessage": "Huisnummer",
"description": "Label for addressNL houseNumber input",
"originalDefault": "House number"
},
@@ -562,14 +572,10 @@
"originalDefault": "Your payment is received and processed."
},
"cBsrax": {
- "defaultMessage": "Huis letter",
+ "defaultMessage": "Huisletter",
"description": "Label for addressNL houseLetter input",
"originalDefault": "House letter"
},
- "cHn60V": {
- "defaultMessage": "You must provide a house number.",
- "originalDefault": "You must provide a house number."
- },
"cKFCTI": {
"defaultMessage": "Nog één toevoegen",
"description": "Edit grid add button, default label text",
@@ -723,8 +729,13 @@
"isTranslated": true,
"originalDefault": "Product"
},
+ "lKBAu3": {
+ "defaultMessage": "Postcode is verplicht.",
+ "description": "ZOD error message when AddressNL houseNumber is provided but not postcode",
+ "originalDefault": "You must provide a postcode."
+ },
"lVNV/d": {
- "defaultMessage": "Huis nummer toevoeging",
+ "defaultMessage": "Huisnummertoevoeging",
"description": "Label for addressNL houseNumberAddition input",
"originalDefault": "House number addition"
},
@@ -784,10 +795,6 @@
"description": "Gesturehandeling mac scroll message.",
"originalDefault": "Use ⌘ + scroll to zoom the map"
},
- "p+11YF": {
- "defaultMessage": "You must provide a postcode.",
- "originalDefault": "You must provide a postcode."
- },
"pguTkQ": {
"defaultMessage": "Intersectie-resultaten kunnen niet samengevoegd worden.",
"description": "ZOD 'invalid_intersection_types' error message",