diff --git a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/NationalIdentityNumber/Examples.tsx b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/NationalIdentityNumber/Examples.tsx index bcc3301f1e8..7bf53f93db6 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/NationalIdentityNumber/Examples.tsx +++ b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/NationalIdentityNumber/Examples.tsx @@ -1,4 +1,5 @@ import ComponentBox from '../../../../../../shared/tags/ComponentBox' +import { createMinimumAgeValidator } from '@dnb/eufemia/src/extensions/forms/Field/NationalIdentityNumber' import { Field } from '@dnb/eufemia/src/extensions/forms' export const Empty = () => { @@ -188,3 +189,51 @@ export const ValidationExtendValidator = () => { ) } + +export const ValidationExtendValidatorAdult = () => { + return ( + + {() => { + const adultValidator = createMinimumAgeValidator(18) + const myAdultValidator = (value, { validators }) => { + const { dnrAndFnrValidator } = validators + + return [dnrAndFnrValidator, adultValidator] + } + + return ( + + ) + }} + + ) +} + +export const ValidationFnrAdult = () => { + return ( + + {() => { + const adultValidator = createMinimumAgeValidator(18) + const myFnrAdultValidator = (value, { validators }) => { + const { fnrValidator } = validators + + return [fnrValidator, adultValidator] + } + + return ( + + ) + }} + + ) +} diff --git a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/NationalIdentityNumber/demos.mdx b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/NationalIdentityNumber/demos.mdx index 2d20256438d..446131cc0b7 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/NationalIdentityNumber/demos.mdx +++ b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/NationalIdentityNumber/demos.mdx @@ -54,18 +54,28 @@ Below is an example of the error message displayed when there's an invalid Norwe It validates [D numbers](https://www.skatteetaten.no/en/person/national-registry/identitetsnummer/d-nummer/) using the [fnrvalidator](https://github.com/navikt/fnrvalidator). -Below is an example of the error message displayed when there's an invalid D number: +Below is an example of the error message displayed when there's an invalid D number(a D number has its first number in the identification number increased by 4): ### Validation function -You can provide your own validation function. +You can provide your own validation function, either to `validator` or `onBlurValidator`. ### Extend validation with custom validation function -You can [extend the existing validations](/uilib/extensions/forms/create-component/useFieldProps/info/#validators)(`dnrValidator`, `fnrValidator`, and `dnrAndFnrValidator`) with your own validation function. +You can [extend the existing validations](/uilib/extensions/forms/create-component/useFieldProps/info/#validators)(`dnrValidator`, `fnrValidator`, `dnrAndFnrValidator`, and make your own age validator by using the `createMinimumAgeValidator` function) with your own validation function. + +### Extend validation with adult validator + +You can [extend the existing validations](/uilib/extensions/forms/create-component/useFieldProps/info/#validators)(`dnrValidator`, `fnrValidator`, and `dnrAndFnrValidator`) with your own age validator, by using the `createMinimumAgeValidator` function. + + + +### Validate only national identity numbers(fnr) above 18 years old + + diff --git a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/NationalIdentityNumber/properties.mdx b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/NationalIdentityNumber/properties.mdx index 694c8830f82..4cd7b9dc2e4 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/NationalIdentityNumber/properties.mdx +++ b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/feature-fields/NationalIdentityNumber/properties.mdx @@ -21,12 +21,25 @@ import { NationalIdentityNumberProperties } from '@dnb/eufemia/src/extensions/fo `Field.NationalIdentityNumber` expose the following validators through its `validator` and `onBlurValidator` property: -- `dnrValidator`: validates a d number. +- `dnrValidator`: validates a D number. - `fnrValidator`: validates a national identity number (fødselsnummer). - `dnrAndFnrValidator`: - - validates the identification number as a d number when first digit is 4 or greater (because a d number has its first number increased by 4). + - validates the identification number as a D number when first digit is 4 or greater (because a D number has its first number increased by 4). - validates the identification number as a national identity number (fødselsnummer) when first digit is 3 or less. +You can create your own age validator by using the `createMinimumAgeValidator` function. It takes an age as a parameter and returns a validator function. The validator function takes a value and returns an error message if the value is not above the given age. +It validates if the identification number has a date of birth that is 18 years or older. It uses only the 7 first digits of the identification number to validate. The first 6 digits representing the birth of date, and the next digit represents the century. +As it only use the 7 first digits, it does not validate the identification number, therefore it's quite common to use this validator together with one of the validators above (`dnrValidator`, `fnrValidator` or `dnrAndFnrValidator`) to validate the identification number as well. + +You need to import the `createMinimumAgeValidator` function from the `Field.NationalIdentityNumber` component: + +```tsx +import { createMinimumAgeValidator } from '@dnb/eufemia/extensions/forms/Field/NationalIdentityNumber' + +// Create a validator that validates if the value is above 18 years old +const above18YearsValidator = createMinimumAgeValidator(18) +``` + See the following [example](/uilib/extensions/forms/feature-fields/NationalIdentityNumber/#extend-validation-with-custom-validation-function) on how to extend validation using the exposed validators. ## Translations diff --git a/packages/dnb-eufemia/src/extensions/forms/Field/NationalIdentityNumber/NationalIdentityNumber.tsx b/packages/dnb-eufemia/src/extensions/forms/Field/NationalIdentityNumber/NationalIdentityNumber.tsx index 5e3420b525f..277f1f3419f 100644 --- a/packages/dnb-eufemia/src/extensions/forms/Field/NationalIdentityNumber/NationalIdentityNumber.tsx +++ b/packages/dnb-eufemia/src/extensions/forms/Field/NationalIdentityNumber/NationalIdentityNumber.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useMemo } from 'react' import StringField, { Props as StringFieldProps } from '../String' import { dnr, fnr } from '@navikt/fnrvalidator' -import { Validator } from '../../types' +import { FormError, Validator } from '../../types' import useErrorMessage from '../../hooks/useErrorMessage' import useTranslation from '../../hooks/useTranslation' @@ -14,18 +14,28 @@ export type Props = Omit & { function NationalIdentityNumber(props: Props) { const translations = useTranslation().NationalIdentityNumber - const { label, errorRequired, errorFnr, errorDnr } = translations + const { + label, + errorRequired, + errorFnr, + errorDnr, + errorMinimumAgeValidator, + } = translations const errorMessages = useErrorMessage(props.path, props.errorMessages, { required: errorRequired, pattern: errorFnr, errorFnr, errorDnr, + errorMinimumAgeValidator, }) const fnrValidator = useCallback( (value: string) => { - // have to check for undefined as @navikt/fnrvalidator does not support undefined - if (value !== undefined && fnr(value).status === 'invalid') { + if ( + value !== undefined && + (Number.parseInt(value.substring(0, 1)) > 3 || + fnr(value).status === 'invalid') + ) { return Error(errorFnr) } }, @@ -34,8 +44,11 @@ function NationalIdentityNumber(props: Props) { const dnrValidator = useCallback( (value: string) => { - // have to check for undefined as @navikt/fnrvalidator does not support undefined - if (value !== undefined && dnr(value).status === 'invalid') { + if ( + value !== undefined && + (Number.parseInt(value.substring(0, 1)) < 4 || + dnr(value).status === 'invalid') + ) { return Error(errorDnr) } }, @@ -106,5 +119,64 @@ function NationalIdentityNumber(props: Props) { return } +export function getAgeByBirthDate(birthDate: Date): number { + const today = new Date() + const age = today.getFullYear() - birthDate.getFullYear() + const month = today.getMonth() - birthDate.getMonth() + const day = today.getDate() - birthDate.getDate() + + if (month < 0 || (month === 0 && day < 0)) { + return age - 1 + } + + return age +} + +export function getBirthDateByFnrOrDnr(value: string) { + if (value === undefined) { + return // stop here + } + + const yearPart = value.substring(4, 6) + const centuryNumber = Number.parseInt(value.substring(6, 7)) + + const isBornIn20XX = centuryNumber >= 5 + const year = isBornIn20XX ? `20${yearPart}` : `19${yearPart}` + const month = Number.parseInt(value.substring(2, 4)) + + const differentiatorValue = + value.length > 0 ? Number.parseInt(value.substring(0, 1)) : undefined + const isDnr = differentiatorValue && differentiatorValue > 3 + + const day = isDnr + ? Number.parseInt(value.substring(0, 2)) - 40 + : Number.parseInt(value.substring(0, 2)) + + return new Date(Number.parseInt(year), month - 1, day) +} + +export function createMinimumAgeValidator(age: number) { + return (value: string) => { + if (typeof value !== 'string') { + return // stop here + } + + if (value.length > 6) { + const date = getBirthDateByFnrOrDnr(value) + if (getAgeByBirthDate(date) >= age) { + return // stop here + } + } + + return new FormError( + 'NationalIdentityNumber.errorMinimumAgeValidator', + { + validationRule: 'errorMinimumAgeValidator', // "validationRule" Will be removed in future PR + messageValues: { age: String(age) }, + } + ) + } +} + NationalIdentityNumber._supportsSpacingProps = true export default NationalIdentityNumber diff --git a/packages/dnb-eufemia/src/extensions/forms/Field/NationalIdentityNumber/__tests__/NationalIdentityNumberAdultValidator.test.tsx b/packages/dnb-eufemia/src/extensions/forms/Field/NationalIdentityNumber/__tests__/NationalIdentityNumberAdultValidator.test.tsx new file mode 100644 index 00000000000..17f7605768d --- /dev/null +++ b/packages/dnb-eufemia/src/extensions/forms/Field/NationalIdentityNumber/__tests__/NationalIdentityNumberAdultValidator.test.tsx @@ -0,0 +1,668 @@ +import React from 'react' +import { render, waitFor, screen } from '@testing-library/react' +import { Field, Validator } from '../../..' +import { createMinimumAgeValidator } from '../NationalIdentityNumber' + +import nbNO from '../../../constants/locales/nb-NO' + +const nb = nbNO['nb-NO'] + +describe('Field.NationalIdentityNumber with adultValidator', () => { + const errorMinimumAgeValidator = + nb.NationalIdentityNumber.errorMinimumAgeValidator.replace( + '{age}', + '18' + ) + const adultValidator = createMinimumAgeValidator(18) + const extendingDnrAndFnrValidatorWithAdultValidator: Validator< + string + > = (value, { validators }) => { + const { dnrAndFnrValidator } = validators + + return [dnrAndFnrValidator, adultValidator] + } + + const extendingDnrValidatorWithAdultValidator: Validator = ( + value, + { validators } + ) => { + const { dnrValidator } = validators + + return [dnrValidator, adultValidator] + } + + const extendingFnrValidatorWithAdultValidator: Validator = ( + value, + { validators } + ) => { + const { fnrValidator } = validators + + return [fnrValidator, adultValidator] + } + + const myAdultValidator: Validator = () => { + return [adultValidator] + } + + it('should display error if required and validateInitially', async () => { + render( + + ) + + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + nb.NationalIdentityNumber.errorRequired + ) + }) + }) + + it('should display error when value is invalid', async () => { + render( + + ) + + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + errorMinimumAgeValidator + ) + }) + }) + + it('should not display error when validateInitially and no value', async () => { + render( + + ) + + await expect(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + }).neverToResolve() + }) + + describe('should validate if identity numbers is adult(18 years and older)', () => { + jest.useFakeTimers().setSystemTime(new Date('2024-10-09').getTime()) + const fnr0YearsOld = [ + '10072476609', + '29082499936', + '03022450718', + '11032455001', + '30082489912', + ] + + const fnr17YearsOld = [ + '31050752669', + '10040752779', + '28050772596', + '25060798446', + '07100782566', + '08100787300', + ] + + const fnrUnder18YearsOld = [...fnr0YearsOld, ...fnr17YearsOld] + + const fnr18Years = [ + '09100654021', + '09100696336', + '24040664900', + '26020682328', + '07070663990', + '11030699302', + '31010699021', + ] + const fnr99Years = [ + '14102535759', + '20042528022', + '14082523414', + '01022537632', + '01022504416', + ] + const fnr18YearsOldTo99 = [ + '25047441741', + '06118836551', + '19042648291', + '18053526132', + '29075642618', + ] + const fnr99To120YearsOld = [ + '22041330302', + '02061234694', + '23020704845', + '28021741177', + '10121933999', + ] + const fnr18YearsOldAndOlder = [ + ...fnr18Years, + ...fnr99Years, + ...fnr18YearsOldTo99, + ...fnr99To120YearsOld, + ] + + const dnrUnder18YearsOld = [ + '42011660597', + '44011957371', + '45010886213', + '60050972871', + '65052062378', + '70121275293', + '71072354979', + '43072496079', + '44052351836', + '56052459244', + '59082354829', + '63032486179', + '48100754692', + ] + const dnr18YearsOldAndOlder = [ + '49100651997', + '49100697466', + '41070663889', + '42020653633', + '41012413597', + '41062421922', + '41080422588', + '44081020024', + '71081924796', + '60067139081', + '60075812380', + ] + + const validIds = [...fnr18YearsOldAndOlder, ...dnr18YearsOldAndOlder] + + const invalidIds = [...fnrUnder18YearsOld, ...dnrUnder18YearsOld] + + const invalidDnums = ['69020112345', '690'] + const invalidFnrs = ['29020112345', '290'] + + describe('when provided as the only validator validation function', () => { + it.each(validIds)( + 'Identity number is 18 years or older : %s', + async (validId) => { + render( + + ) + + await expect(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + }).neverToResolve() + } + ) + + it.each(invalidIds)( + 'Invalid identity number is not 18 years or older: %s', + async (invalidId) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + errorMinimumAgeValidator + ) + }) + } + ) + }) + + describe('when provided as the only onBlurValidation validation function', () => { + it.each(validIds)( + 'Identity number is 18 years or older : %s', + async (validId) => { + render( + + ) + + await expect(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + }).neverToResolve() + } + ) + + it.each(invalidIds)( + 'Invalid identity number is not 18 years or older: %s', + async (invalidId) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + errorMinimumAgeValidator + ) + }) + } + ) + }) + + describe('when extending the dnrAndFnrValidator as validator', () => { + it.each(validIds)( + 'Identity number is 18 years or older : %s', + async (validId) => { + render( + + ) + + await expect(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + }).neverToResolve() + } + ) + + it.each(invalidIds)( + 'Invalid identity number is not 18 years or older: %s', + async (invalidId) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + errorMinimumAgeValidator + ) + }) + } + ) + + it.each(invalidDnums)( + 'Invalid identity number is not 18 years or older: %s', + async (invalidDnum) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + nb.NationalIdentityNumber.errorDnr + ) + }) + } + ) + + it.each(invalidFnrs)( + 'Invalid identity number is not 18 years or older: %s', + async (invalidFnr) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + nb.NationalIdentityNumber.errorFnr + ) + }) + } + ) + }) + + describe('when extending the dnrAndFnrValidator as onBlurValidator', () => { + it.each(validIds)( + 'Identity number is 18 years or older : %s', + async (validId) => { + render( + + ) + + await expect(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + }).neverToResolve() + } + ) + + it.each(invalidIds)( + 'Invalid identity number is not 18 years or older: %s', + async (invalidId) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + errorMinimumAgeValidator + ) + }) + } + ) + + it.each(invalidDnums)( + 'Invalid identity number is not 18 years or older: %s', + async (invalidDnum) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + nb.NationalIdentityNumber.errorDnr + ) + }) + } + ) + + it.each(invalidFnrs)( + 'Invalid identity number is not 18 years or older: %s', + async (invalidFnr) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + nb.NationalIdentityNumber.errorFnr + ) + }) + } + ) + }) + + describe('when extending the dnrValidator as validator', () => { + it.each(dnr18YearsOldAndOlder)( + 'D number is 18 years or older : %s', + async (validDnum) => { + render( + + ) + + await expect(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + }).neverToResolve() + } + ) + + it.each(dnrUnder18YearsOld)( + 'D number is not 18 years or older: %s', + async (invalidDnum) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + errorMinimumAgeValidator + ) + }) + } + ) + + it.each([...invalidDnums, ...invalidFnrs, ...fnr18YearsOldAndOlder])( + 'Invalid d number: %s', + async (invalidDnum) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + nb.NationalIdentityNumber.errorDnr + ) + }) + } + ) + }) + + describe('when extending the dnrValidator as onBlurValidator', () => { + it.each(dnr18YearsOldAndOlder)( + 'D number is 18 years or older : %s', + async (validDnum) => { + render( + + ) + + await expect(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + }).neverToResolve() + } + ) + + it.each(dnrUnder18YearsOld)( + 'D number is not 18 years or older: %s', + async (invalidDnum) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + errorMinimumAgeValidator + ) + }) + } + ) + + it.each([ + ...invalidDnums, + ...invalidFnrs, + ...fnr18YearsOldAndOlder, + ...fnrUnder18YearsOld, + ])('Invalid d number: %s', async (invalidDnum) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + nb.NationalIdentityNumber.errorDnr + ) + }) + }) + }) + + describe('when extending the fnrValidator as validator', () => { + it.each(fnr18YearsOldAndOlder)( + 'Identity number(fnr) is 18 years or older : %s', + async (validFnr) => { + render( + + ) + + await expect(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + }).neverToResolve() + } + ) + + it.each(fnrUnder18YearsOld)( + 'Identity number(fnr) is not 18 years or older: %s', + async (invalidFnr) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + errorMinimumAgeValidator + ) + }) + } + ) + + it.each([...invalidFnrs, ...invalidDnums, ...dnr18YearsOldAndOlder])( + 'Invalid identity number(fnr): %s', + async (invalidFnr) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + nb.NationalIdentityNumber.errorFnr + ) + }) + } + ) + }) + + describe('when extending the fnrValidator as onBlurValidator', () => { + it.each(fnr18YearsOldAndOlder)( + 'Identity number(fnr) is 18 years or older : %s', + async (validFnr) => { + render( + + ) + + await expect(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + }).neverToResolve() + } + ) + + it.each(fnrUnder18YearsOld)( + 'Identity number(fnr) is not 18 years or older: %s', + async (invalidFnr) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + errorMinimumAgeValidator + ) + }) + } + ) + + it.each([ + ...invalidFnrs, + ...invalidDnums, + ...dnr18YearsOldAndOlder, + ...dnrUnder18YearsOld, + ])('Invalid identity number(fnr): %s', async (invalidFnr) => { + render( + + ) + await waitFor(() => { + expect(screen.queryByRole('alert')).toBeInTheDocument() + expect(screen.queryByRole('alert')).toHaveTextContent( + nb.NationalIdentityNumber.errorFnr + ) + }) + }) + }) + }) +}) diff --git a/packages/dnb-eufemia/src/extensions/forms/Field/NationalIdentityNumber/stories/NationalIdentityNumber.stories.tsx b/packages/dnb-eufemia/src/extensions/forms/Field/NationalIdentityNumber/stories/NationalIdentityNumber.stories.tsx index a6870b12bf2..02b55500e24 100644 --- a/packages/dnb-eufemia/src/extensions/forms/Field/NationalIdentityNumber/stories/NationalIdentityNumber.stories.tsx +++ b/packages/dnb-eufemia/src/extensions/forms/Field/NationalIdentityNumber/stories/NationalIdentityNumber.stories.tsx @@ -1,16 +1,758 @@ import React from 'react' -import { Field } from '../../..' +import { Field, Validator } from '../../..' +import { Wrapper } from 'storybook-utils/helpers' +import { createMinimumAgeValidator } from '../NationalIdentityNumber' export default { title: 'Eufemia/Extensions/Forms/NationalIdentityNumber', } -export function NationalIdentityNumber() { +const simpleValidator = (value) => { + return value?.length < 4 ? Error('At least 4 characters') : undefined +} + +const adultValidator = createMinimumAgeValidator(18) + +const myAdultValidator: Validator = () => { + return [adultValidator] +} + +const myAdultFnrDnrValidator: Validator = ( + value, + { validators } +) => { + const { dnrAndFnrValidator } = validators + + return [dnrAndFnrValidator, adultValidator] +} + +const myFnrValidator: Validator = (value, { validators }) => { + const { fnrValidator } = validators + + return [fnrValidator] +} + +const myDnrValidator: Validator = (value, { validators }) => { + const { dnrValidator } = validators + + return [dnrValidator] +} + +const myFnrAndDnrValidator: Validator = ( + value, + { validators } +) => { + const { dnrAndFnrValidator } = validators + + return [dnrAndFnrValidator] +} + +export function ValidatorsUndefinedFalse() { return ( - <> + + + + +

Validate Initially:

+ + + +
+ ) +} + +export function NationalIdentityNumberDefault() { + return ( + - - + +

Validate Initially:

+ + + +
+ ) +} + +export function NationalIdentityNumberAndDNumberOnBlurValidator() { + return ( + + + + +

Validate Initially:

+ + + +
+ ) +} + +export function NationalIdentityNumberOnBlurValidator() { + return ( + + + + +

Validate Initially:

+ + + +
+ ) +} + +export function NationalIdentityNumberValidator() { + return ( + + + + +

Validate Initially:

+ + + +
+ ) +} + +export function DNumberOnBlurValidator() { + return ( + + + + +

Validate Initially:

+ + + +
+ ) +} + +export function DNumberValidator() { + return ( + + + + +

Validate Initially:

+ + + +
+ ) +} + +export function AdultOnBlurValidator() { + return ( + + + + + + + +

Validate Initially:

+ + + + + + +
+ ) +} + +export function AdultValidator() { + return ( + + + + + + + +

Validate Initially:

+ + + + + + +
+ ) +} + +export function AdultOnBlurValidatorAndDefaultValidator() { + return ( + + + + + + +

Validate Initially:

+ + + + + +
+ ) +} + +export function AdultValidatorAndDefaultValidator() { + return ( + + + + + + +

Validate Initially:

+ + + + + +
+ ) +} + +export function CustomValidatorFunction() { + return ( + + + + + + +

Validate Initially:

+ + + + + +
+ ) +} + +export function CustomOnBlurValidatorFunction() { + return ( + + + + + + +

Validate Initially:

+ + + + + +
+ ) +} + +export function CustomValidatorFunctionReturnArray() { + const validatorX = (value) => { + return value?.length < 4 ? Error('At least 4 characters') : undefined + } + + const simpleValidator = () => { + return [validatorX] + } + + return ( + + + + + + +

Validate Initially:

+ + + + + +
+ ) +} + +export function CustomOnBlurValidatorFunctionReturnArray() { + const validatorX = (value) => { + return value?.length < 4 ? Error('At least 4 characters') : undefined + } + + const simpleValidator = () => { + return [validatorX] + } + + return ( + + + + + + +

Validate Initially:

+ + + + + +
) } diff --git a/packages/dnb-eufemia/src/extensions/forms/constants/locales/en-GB.ts b/packages/dnb-eufemia/src/extensions/forms/constants/locales/en-GB.ts index cb609a0fbfa..f11dacd1276 100644 --- a/packages/dnb-eufemia/src/extensions/forms/constants/locales/en-GB.ts +++ b/packages/dnb-eufemia/src/extensions/forms/constants/locales/en-GB.ts @@ -120,6 +120,7 @@ export default { errorRequired: 'You must enter a national identity number.', errorFnr: 'Invalid national identity number.', errorDnr: 'Invalid D number.', + errorMinimumAgeValidator: 'Must be at least {age} years of age.', }, OrganizationNumber: { label: 'Organisation number', diff --git a/packages/dnb-eufemia/src/extensions/forms/constants/locales/nb-NO.ts b/packages/dnb-eufemia/src/extensions/forms/constants/locales/nb-NO.ts index 309b6f1266b..e37d5d82b2d 100644 --- a/packages/dnb-eufemia/src/extensions/forms/constants/locales/nb-NO.ts +++ b/packages/dnb-eufemia/src/extensions/forms/constants/locales/nb-NO.ts @@ -118,6 +118,7 @@ export default { errorRequired: 'Du må fylle inn et fødselsnummer.', errorFnr: 'Ugyldig fødselsnummer.', errorDnr: 'Ugyldig d-nummer.', + errorMinimumAgeValidator: 'Må være minst {age} år.', }, OrganizationNumber: { label: 'Organisasjonsnummer',