Skip to content

Commit

Permalink
feat(Forms): add support for minItems/maxItems error messages to …
Browse files Browse the repository at this point in the history
…Field.ArraySelection (#4120)

With the use of JSON Schema and ajv's validation, `ArraySelection`
supports setting `minItems` and `maxItems` to control how many items the
user can select. The validation error message types are however not
exposed, thus TypeScript won't let you override them.

---------

Co-authored-by: Sindre Haugland Bøyum <[email protected]>
  • Loading branch information
boyum and Sindre Haugland Bøyum authored Oct 18, 2024
1 parent 07b257f commit 29ebe55
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import classnames from 'classnames'
import FieldBlock from '../../FieldBlock'
import { useFieldProps } from '../../hooks'
import { ReturnAdditional } from '../../hooks/useFieldProps'
import { FieldHelpProps, FieldProps, FormError, Path } from '../../types'
import {
DefaultErrorMessages,
FieldHelpProps,
FieldProps,
FormError,
Path,
} from '../../types'
import { pickSpacingProps } from '../../../../components/flex/utils'
import { getStatus, mapOptions, Data } from '../Selection'
import { HelpButtonProps } from '../../../../components/HelpButton'
Expand Down Expand Up @@ -40,6 +46,11 @@ export type Props = FieldHelpProps &
* The generated options will be placed above given JSX based children.
*/
data?: Data

errorMessages?: DefaultErrorMessages & {
minItems?: string
maxItems?: string
}
}

function ArraySelection(props: Props) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,45 @@ describe('ArraySelection', () => {
)
expect(option3).not.toHaveClass('dnb-toggle-button--checked')
})

it('displays correct error messages for minItems and maxItems', () => {
const data = [
{ value: 'oslo', title: 'Oslo' },
{ value: 'stockholm', title: 'Stockholm' },
{ value: 'copenhagen', title: 'Copenhagen' },
{ value: 'helsinki', title: 'Helsinki' },
]

render(
<Field.ArraySelection
label="Select cities"
data={data}
schema={{
type: 'array',
minItems: 2,
maxItems: 3,
}}
errorMessages={{
minItems: 'You must select at least two',
maxItems: 'You can only select up to three',
}}
/>
)

// Trying to select only one item
fireEvent.click(screen.getByText('Oslo'))
expect(
screen.getByText('You must select at least two')
).toBeInTheDocument()

// Trying to select four items
fireEvent.click(screen.getByText('Stockholm'))
fireEvent.click(screen.getByText('Copenhagen'))
fireEvent.click(screen.getByText('Helsinki'))
expect(
screen.getByText('You can only select up to three')
).toBeInTheDocument()
})
}
)
})
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react'
import { Card, Section } from '../../../../../components'
import { Field, Form } from '../../..'

Expand Down Expand Up @@ -72,3 +71,46 @@ export function NestingWithLogic() {
</Form.Handler>
)
}

export function SelectUpToThree() {
const data = [
{ value: 'oslo', title: 'Oslo' },
{ value: 'stockholm', title: 'Stockholm' },
{ value: 'copenhagen', title: 'Copenhagen' },
{ value: 'helsinki', title: 'Helsinki' },
{ value: 'reykjavik', title: 'Reykjavik' },
{ value: 'antananarivo', title: 'Antananarivo' },
{ value: 'nuuk', title: 'Nuuk' },
{ value: 'nairobi', title: 'Nairobi' },
{ value: 'tokyo', title: 'Tokyo' },
]

return (
<Card stack>
<Field.ArraySelection
label={
<>
Which capitals would you most like to visit?
<br />
<em style={{ fontSize: '0.8em' }}>
Select between two and three
</em>
</>
}
required
optionsLayout="horizontal"
variant="button"
data={data}
schema={{
type: 'array',
minItems: 2,
maxItems: 3,
}}
errorMessages={{
minItems: 'You must select at least two',
maxItems: 'You can only select up to three',
}}
/>
</Card>
)
}

0 comments on commit 29ebe55

Please sign in to comment.