Skip to content

Import

import { Field } from '@dnb/eufemia/extensions/forms'
render(<Field.Selection />)

Description

Field.Selection is a component for selecting between options using a dropdown or similar user experiences.

Before using this component, ensure there is not a more specific field component available that better suits your needs.

Uses the Field.Option pseudo-component to define options.

There is a corresponding Value.Selection component.

import { Field } from '@dnb/eufemia/extensions/forms'
render(
<Field.Selection placeholder="Select something...">
<Field.Option value="foo" title="Foo!" />
<Field.Option value="bar" title="Baar!" />
</Field.Selection>
)

You can also use the dataPath property to provide the data to the component:

import { Field } from '@dnb/eufemia/extensions/forms'
render(
<Form.Handler
data={{
myDataPath: [
{ title: 'Foo!', value: 'foo' },
{ title: 'Bar!', value: 'bar' },
],
}}
>
<Field.Selection dataPath="/myDataPath" />
</Form.Handler>
)

Relevant links

About the Autocomplete variant

The autocomplete variant (variant="autocomplete") is a special easy drop-in version – basically as a replacement for the Dropdown variant, but with a search capability.

The Autocomplete by itself can be customized and used in various ways. If you need more control, you can use the autocompleteProps property to forward any additional properties (camelCase) to the Autocomplete component.

Demos

Variants summary

As there are many variants, they are split into separate sections. Here is a summary of the variants:

Dropdown

<Field.Selection
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Autocomplete

<Field.Selection
  variant="autocomplete"
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Radio buttons

Label text
<Field.Selection
  variant="radio"
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Toggle buttons

Label text
<Field.Selection
  variant="button"
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Dropdown variant (default)

Dropdown empty

<Field.Selection
  onFocus={(value) => console.log('onFocus', value)}
  onBlur={(value) => console.log('onBlur', value)}
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Dropdown placeholder

<Field.Selection
  placeholder="Select something..."
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Dropdown with a transformed selection text

<Field.Selection
  label="Label"
  value="bar"
  transformSelection={({ title }) => {
    return title
  }}
>
  <Field.Option value="foo" title="Foo!" text="Additional text" />
  <Field.Option value="bar" title="Baar!" text="Additional text" />
</Field.Selection>

Dropdown label and option selected

<Field.Selection
  value="bar"
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Dropdown with help

<Field.Selection
  value="bar"
  label="Label text"
  help={{
    title: 'Help is available',
    content:
      'Somewhere along the way, we must learn that there is nothing greater than to do something for others.',
  }}
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Horizontal layout

<Field.Selection
  value="bar"
  label="Label text"
  layout="horizontal"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Dropdown disabled

<Field.Selection
  value="bar"
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
  disabled
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Dropdown option disabled

const Example = () => {
  return (
    <Field.Selection label="Label text">
      <Field.Option value="foo" title="Foo!" disabled />
      <Field.Option value="bar" title="Baar!" />
    </Field.Selection>
  )
}
render(<Example />)

Dropdown error

This is what is wrong...
<Field.Selection
  value="bar"
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
  error={new Error('This is what is wrong...')}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Dropdown dynamic options

const Example = () => {
  const [numOptions, setNumOptions] = React.useState(3)
  return (
    <>
      <Field.Selection
        value="option-15"
        label="Label text"
        onChange={(value) => console.log('onChange', value)}
      >
        {Array.from(Array(numOptions).keys()).map((key) => (
          <Field.Option
            key={key}
            value={key}
            title={`Option ${key + 1}`}
          />
        ))}
      </Field.Selection>

      <p>
        {[3, 4, 5].map((num, i) => (
          <Button
            key={i}
            size="medium"
            right="x-small"
            variant={numOptions === num ? 'primary' : 'secondary'}
            onClick={() => setNumOptions(num)}
          >
            {num} options
          </Button>
        ))}
      </p>
    </>
  )
}
render(<Example />)

Dropdown high number of options

<Field.Selection
  value="option-15"
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="option-1" title="One" />
  <Field.Option value="option-2" title="Two" />
  <Field.Option value="option-3" title="Three" />
  <Field.Option value="option-4" title="Four" />
  <Field.Option value="option-5" title="Five" />
  <Field.Option value="option-6" title="Six" />
  <Field.Option value="option-7" title="Seven" />
  <Field.Option value="option-8" title="Eight" />
  <Field.Option value="option-9" title="Nine" />
  <Field.Option value="option-10" title="Ten" />
  <Field.Option value="option-11" title="Eleven" />
  <Field.Option value="option-12" title="Twelve" />
  <Field.Option value="option-13" title="Thirteen" />
  <Field.Option value="option-14" title="Fourteen" />
  <Field.Option value="option-15" title="Fifteen" />
  <Field.Option value="option-16" title="Sixteen" />
  <Field.Option value="option-17" title="Seventeen" />
  <Field.Option value="option-18" title="Eighteen" />
  <Field.Option value="option-19" title="Nineteen" />
  <Field.Option value="option-20" title="Twenty" />
  <Field.Option value="option-21" title="Twenty-one" />
  <Field.Option value="option-22" title="Twenty-two" />
  <Field.Option value="option-23" title="Twenty-three" />
  <Field.Option value="option-24" title="Twenty-four" />
  <Field.Option value="option-25" title="Twenty-five" />
</Field.Selection>

Dropdown validation - Required

<Field.Selection
  value="foo"
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
  onFocus={(value) => console.log('onFocus', value)}
  onBlur={(value) => console.log('onBlur', value)}
  required
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Dropdown button with a path to populate the data

<Form.Handler
  data={{
    example: {
      list: [
        {
          title: 'One',
          value: 'one',
        },
        {
          title: 'Two',
          value: 'two',
        },
      ],
    },
    selection: 'two',
  }}
>
  <Field.Selection
    label="Label text"
    path="/selection"
    dataPath="/example/list"
  >
    <Field.Option value="foo">Fooo</Field.Option>
  </Field.Selection>
</Form.Handler>

Dropdown with the data property

<Field.Selection
  label="Label text"
  data={[
    {
      title: 'One',
      value: 'one',
    },
    {
      title: 'Two',
      value: 'two',
    },
  ]}
/>

Dropdown widths

Dropdown groups

<Field.Selection
  label="Label text"
  path="/selection"
  dataPath="/example/list"
  groups={['Foos', 'Bars']}
>
  <Field.Option value="foo" groupIndex={0}>
    Fooo
  </Field.Option>
  <Field.Option value="bar" groupIndex={1}>
    Bar
  </Field.Option>
</Field.Selection>

Autocomplete variant

<Field.Selection
  variant="autocomplete"
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
  onFocus={(value) => console.log('onFocus', value)}
  onBlur={(value) => console.log('onBlur', value)}
  required
  validateInitially
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Autocomplete groups

<Field.Selection
  variant="autocomplete"
  label="Label text"
  path="/selection"
  dataPath="/example/list"
  groups={['Foos', 'Bars']}
>
  <Field.Option value="foo" groupIndex={0}>
    Fooo
  </Field.Option>
  <Field.Option value="bar" groupIndex={1}>
    Bar
  </Field.Option>
</Field.Selection>

Radio variant

Radio empty

<Field.Selection
  variant="radio"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Radio option selected

Label text
<Field.Selection
  variant="radio"
  label="Label text"
  value="bar"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Radio horizontal layout

Label text
<Field.Selection
  variant="radio"
  label="Label text"
  value="bar"
  layout="horizontal"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Radio horizontal options-layout

Label text
<Field.Selection
  variant="radio"
  label="Label text"
  value="bar"
  optionsLayout="horizontal"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Radio horizontal layout and horizontal options-layout

Label text
<Field.Selection
  variant="radio"
  label="Label text"
  value="bar"
  layout="horizontal"
  optionsLayout="horizontal"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Radio disabled

Label text
<Field.Selection
  variant="radio"
  value="bar"
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
  disabled
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Radio option disabled

Label text
const Example = () => {
  return (
    <Field.Selection label="Label text" variant="radio">
      <Field.Option value="foo" title="Foo!" disabled />
      <Field.Option value="bar" title="Baar!" />
    </Field.Selection>
  )
}
render(<Example />)

Radio error

Label text
This is what is wrong...
<Field.Selection
  variant="radio"
  value="bar"
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
  error={new Error('This is what is wrong...')}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

Radio button with a path to populate the data

Label text
<Form.Handler
  data={{
    example: {
      list: [
        {
          title: 'One',
          value: 'one',
        },
        {
          title: 'Two',
          value: 'two',
        },
      ],
    },
    selection: 'two',
  }}
>
  <Field.Selection
    variant="radio"
    label="Label text"
    path="/selection"
    dataPath="/example/list"
  >
    <Field.Option value="foo">Fooo</Field.Option>
  </Field.Selection>
</Form.Handler>

Radio with the data property

Label text
<Field.Selection
  variant="radio"
  label="Label text"
  data={[
    {
      title: 'One',
      value: 'one',
    },
    {
      title: 'Two',
      value: 'two',
    },
  ]}
/>

Radio with List composition

Use render prop children to compose each option with List and set selected state from the current field value.

Select an option
<Form.Handler
  defaultData={{
    selection: 'bar',
    myDataPath: [
      {
        value: 'foo',
        title: 'Foo!',
        amount: 1234,
      },
      {
        value: 'bar',
        title: 'Baar!',
        amount: 5678,
      },
      {
        value: 'baz',
        title: 'Baz!',
        amount: 9999,
      },
    ],
  }}
>
  <Field.Selection
    label="Select an option"
    variant="radio"
    path="/selection"
    dataPath="/myDataPath"
    width="large"
  >
    {({ value: selectedValue, options = [] }) => {
      return (
        <List.Container>
          {options.map(({ value, title, amount }) => {
            return (
              <List.Item.Basic
                key={value}
                selected={value === selectedValue}
              >
                <List.Cell.Start>
                  <Field.Option value={value} title={title} />
                </List.Cell.Start>
                <List.Cell.End>
                  <Value.Currency value={amount} />
                </List.Cell.End>
              </List.Item.Basic>
            )
          })}
        </List.Container>
      )
    }}
  </Field.Selection>
</Form.Handler>

Radio nesting other fields with logic

You can nest other fields and show them based on your desired logic.

Make a selection

Radio nesting advanced

First selection

Buttons variant

ToggleButton empty

<Field.Selection
  variant="button"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

ToggleButton option selected

Label text
<Field.Selection
  variant="button"
  label="Label text"
  value="bar"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

ToggleButton horizontal options-layout

Label text
<Field.Selection
  variant="button"
  label="Label text"
  optionsLayout="horizontal"
  onChange={(value) => console.log('onChange', value)}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

ToggleButton disabled

Label text
<Field.Selection
  variant="button"
  value="bar"
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
  disabled
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

ToggleButton option disabled

Label text
const Example = () => {
  return (
    <Field.Selection label="Label text" variant="button">
      <Field.Option value="foo" title="Foo!" disabled />
      <Field.Option value="bar" title="Baar!" />
    </Field.Selection>
  )
}
render(<Example />)

ToggleButton error

Label text
This is what is wrong...
<Field.Selection
  variant="button"
  value="bar"
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
  error={new Error('This is what is wrong...')}
>
  <Field.Option value="foo" title="Foo!" />
  <Field.Option value="bar" title="Baar!" />
</Field.Selection>

ToggleButton nesting other fields with logic

You can nest other fields and show them based on your desired logic.

Make a selection
<Form.Handler>
  <Form.Card>
    <Field.Selection
      variant="button"
      label="Make a selection"
      path="/mySelection"
    >
      <Field.Option value="nothing" title="Nothing" />

      <Field.Option value="showInput" title="Show an input" />
      <Form.Visibility
        animate
        visibleWhen={{
          path: '/mySelection',
          hasValue: 'showInput',
        }}
      >
        <Section variant="information" innerSpace>
          <Field.String placeholder="Enter some value" />
        </Section>
      </Form.Visibility>

      <Field.Option
        value="showAdditionalOption"
        title="Show additional option"
      />
      <Form.Visibility
        animate
        visibleWhen={{
          path: '/mySelection',
          hasValue: (value) =>
            value === 'showAdditionalOption' || value === 'showMeMore',
        }}
      >
        <Field.Option
          value="showMeMore"
          title="Show even more"
          bottom="x-small"
        />
        <Form.Visibility
          animate
          visibleWhen={{
            path: '/mySelection',
            hasValue: 'showMeMore',
          }}
        >
          <Section variant="information" innerSpace>
            <Field.String placeholder="Enter more info" />
          </Section>
        </Form.Visibility>
      </Form.Visibility>
    </Field.Selection>
  </Form.Card>
</Form.Handler>

ToggleButton with a path to populate the data

Label text
<Form.Handler
  data={{
    example: {
      list: [
        {
          title: 'One',
          value: 'one',
        },
        {
          title: 'Two',
          value: 'two',
        },
      ],
    },
    selection: 'two',
  }}
>
  <Field.Selection
    variant="button"
    label="Label text"
    path="/selection"
    dataPath="/example/list"
  >
    <Field.Option value="foo">Fooo</Field.Option>
  </Field.Selection>
</Form.Handler>

ToggleButton with the data property

Label text
<Field.Selection
  variant="button"
  label="Label text"
  data={[
    {
      title: 'One',
      value: 'one',
    },
    {
      title: 'Two',
      value: 'two',
    },
  ]}
/>