Skip to content

Import

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

Description

Field.Number is the base component for receiving user input where the target data is of type number.

There is a corresponding Value.Number component.

import { Field } from '@dnb/eufemia/extensions/forms'
render(<Field.Number path="/myNumber" />)

Relevant links

When to use and not to use

Field.Number only allows the user to enter numbers (negative and positive) and decimal numbers.

If a number has the type of number, and cannot start with a zero, this field may be considered.

But for e.g. a customer number, you rather use Field.String.

Internally, it is used by e.g. Field.Currency.

Browser autofill

Check out the Field.String docs about autocomplete.

Step controls

When using showStepControls, the Number component provides buttons for decrementing and incrementing the input value, where the value of de/increment is determined by the step property.

It can also be used with Field.Currency.

Accessibility

The component does not include focusable buttons, aligning with accessibility considerations for keyboard-only users, who can utilize arrow keys for navigation, like the incrementable number input.

One of the reasons to make the buttons as not focusable is to avoid the keyboard-only users to tab through all the extra buttons during navigation.

Due to technical constraint, the Field.Number component will be announced as a stepper field – but will get the same instructions read out by a screen reader like VoiceOver, on how to change the value.

Demos

Label and value

Code Editor
<Field.Number
  label="Label text"
  defaultValue={420000.25}
  onChange={(value) => console.log('onChange', value)}
/>

Label and description

Code Editor
<Form.Card>
  <Field.Number
    label="Label text"
    labelDescription="Description text on the next line"
    placeholder="Enter a text..."
  />
  <Field.Number
    label="Label text"
    labelDescription="Description text on the same line"
    labelDescriptionInline
    placeholder="Enter a text..."
  />
</Form.Card>

With a horizontal layout

This example uses Field.Provider to set the layout to horizontal and layoutOptions to { width: 'medium' } for all nested fields.

The width of the horizontal label can be set to small, medium, large or a rem value.

Aliqua eu aute id qui esse aliqua dolor in aute magna commodo anim enim et.
Code Editor
<Form.Card>
  <Field.Provider
    layout="horizontal"
    layoutOptions={{
      width: 'medium', // can be a rem value
    }}
    required
  >
    <Field.Number
      label="Label text"
      defaultValue={420000}
      step={10000}
      showStepControls
    />
    <Field.Number
      label="Label with a long text that will wrap"
      placeholder="Enter a number..."
      info="Aliqua eu aute id qui esse aliqua dolor in aute magna commodo anim enim et."
    />
    <Field.Number
      label="Label with a long text that will wrap"
      placeholder="Enter a number..."
      size="large"
      width="stretch"
    />
  </Field.Provider>
</Form.Card>

Placeholder

Code Editor
<Field.Number
  label="Label text"
  placeholder="Enter a number..."
  onChange={(value) => console.log('onChange', value)}
/>

With custom mask

Code Editor
<Field.Number
  label="Label text"
  defaultValue={1234}
  mask={Array(4).fill(/\d/)}
  onChange={(value) => console.log('onChange', value)}
/>

With a status

This example demonstrates how the status message width adjusts according to the field width.

Short warning.
Aliqua eu aute id qui esse aliqua dolor in aute magna commodo anim enim et.
Aliqua eu aute id qui esse aliqua dolor in aute magna commodo anim enim et. Velit incididunt exercitation est magna ex irure dolore nisi eiusmod ea exercitation.
Code Editor
<Form.Card>
  <Field.Number
    label="Label text"
    placeholder="Enter a number..."
    width="large"
    warning="Short warning."
    required
  />
  <Field.Number
    label="Label text"
    defaultValue={420000}
    width="large"
    info="Aliqua eu aute id qui esse aliqua dolor in aute magna commodo anim enim et."
    required
  />
  <Field.Number
    label="Label text"
    value={1234}
    width="small"
    warning="Aliqua eu aute id qui esse aliqua dolor in aute magna commodo anim enim et. Velit incididunt exercitation est magna ex irure dolore nisi eiusmod ea exercitation."
    required
  />
</Form.Card>

With help

Code Editor
<Field.Number
  defaultValue={12345}
  label="Label text"
  help={{
    title: 'Help is available',
    content:
      'Here is what a team can do for you. . . . It allows you to help others do their best.',
  }}
  onChange={(value) => console.log('onChange', value)}
/>

Exclusive minimum and exclusive maximum

Code Editor
<Field.Number
  defaultValue={1000}
  label="Label text"
  allowNegative={false}
  required
  exclusiveMinimum={900}
  exclusiveMaximum={1000}
  validateInitially
/>

Prefix and suffix

You can also use a function as a prefix or suffix.

Code Editor
<Flex.Stack>
  <Field.Number
    defaultValue={1234}
    label="With prefix"
    prefix="prefix "
    onChange={(value) => console.log('onChange', value)}
  />
  <Field.Number
    defaultValue={1}
    label="With suffix (function)"
    suffix={(value) => (value === 1 ? ' year' : ' years')}
    onChange={(value) => console.log('onChange', value)}
  />
</Flex.Stack>

Alignment

Code Editor
<Flex.Stack>
  <Field.Number
    align="center"
    label="Center aligned (default)"
    defaultValue={10}
    onChange={(value) => console.log('onChange', value)}
  />
  <Field.Number
    align="left"
    label="Left aligned"
    defaultValue={10}
    onChange={(value) => console.log('onChange', value)}
  />
  <Field.Number
    align="right"
    label="Right aligned"
    defaultValue={10}
    onChange={(value) => console.log('onChange', value)}
  />
</Flex.Stack>

With help

Code Editor
<Field.Number
  defaultValue={12345}
  label="Label text"
  help={{
    title: 'Help is available',
    content:
      'Here is what a team can do for you. . . . It allows you to help others do their best.',
  }}
  onChange={(value) => console.log('onChange', value)}
/>

With step controls

Code Editor
<Field.Number
  label="Label text"
  showStepControls
  minimum={0}
  maximum={100}
  step={10}
  defaultValue={50}
/>

With step controls in conjunction with Slider

Disabled

Code Editor
<Field.Number
  defaultValue={135}
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
  disabled
/>

Validation - Required

Code Editor
<Field.Number
  defaultValue={123}
  label="Label text"
  onChange={(value) => console.log('onChange', value)}
  required
/>

Validation - Minimum

Code Editor
<Field.Number
  defaultValue={300}
  label="Enter a number below 250 and blur to trigger error"
  onChange={(value) => console.log('onChange', value)}
  minimum={250}
/>

Validation - Maximum and custom error message

Code Editor
<Field.Number
  label="Enter a number above 250 and blur to trigger error"
  defaultValue={200}
  maximum={250}
  errorMessages={{
    maximum: "You can't enter a number THAR large.. Max 250!",
  }}
  onChange={(value) => console.log('onChange', value)}
/>

Displaying messages - Conditional info message

You can provide a function to the info, warning or error properties that returns a message based on your conditions.

<Field.String
info={(value) => {
if (value === '123') {
return 'The value is 123'
}
}}
/>

Optionally, use the conditionally higher order function to show the message only when the field got changed (onChange) and blurred (onBlur).

<Field.String
info={(value, { conditionally, getValueByPath, getFieldByPath }) => {
if (value === '123') {
// Show this message only when the field got changed and blurred.
return conditionally(() => 'The value is 123')
}
}}
/>

You can also pass options to the conditionally function:

  • showInitially – display the message when the field is first rendered.
<Field.String
info={(value, { conditionally, getValueByPath, getFieldByPath }) => {
if (value === '123') {
// Show this message only when the field got changed and blurred.
return conditionally(() => 'The value is 123', {
showInitially: true,
})
}
}}
/>

Down below you can see an example of how to use the conditionally function. There are two input fields which depend on each other. Here we use info to show a message when the value of the first field is too low. While we use an error message when the value of the second field is more than what the first field has. The info on the first field will only be shown when the user has changed the value and blurred the field.

Read more about validation and the user experience.

Code Editor
render(
  <Form.Handler
    defaultData={{
      maximum: 4,
      amount: 5,
    }}
    onSubmit={async (data) => {
      console.log('onSubmit', data)
    }}
  >
    <Form.Card>
      <Field.Number
        label="Maximum for amount"
        labelDescription={
          <>Defines the maximum amount possible to be entered.</>
        }
        path="/maximum"
        required
        info={(
          maximum,
          { conditionally, getValueByPath, getFieldByPath },
        ) => {
          return conditionally(() => {
            if (maximum < getValueByPath('/amount')) {
              const { props, id } = getFieldByPath('/amount')
              const anchor = props?.label && (
                <Anchor
                  href={'#' + id + '-label'}
                  onClick={(event) => {
                    event.preventDefault()
                    const el = document.getElementById(id + '-label')
                    el?.scrollIntoView()
                  }}
                >
                  {props.label}
                </Anchor>
              )
              return (
                anchor && (
                  <>
                    Remember to adjust the {anchor} to be {maximum} or
                    lower.
                  </>
                )
              )
            }
          })
        }}
      />
      <Field.Number
        label="Amount"
        labelDescription={<>Should be same or lower than maximum.</>}
        path="/amount"
        required
        onBlurValidator={(amount: number, { connectWithPath }) => {
          const maximum = connectWithPath('/maximum').getValue()
          if (amount > maximum) {
            return new FormError('NumberField.errorMaximum', {
              messageValues: {
                maximum: maximum.toString(),
              },
            })
          }
        }}
      />
    </Form.Card>

    <Form.SubmitButton />
  </Form.Handler>,
)

Percentage

Code Editor
<Field.Number
  percent
  defaultValue={80}
  label="Percentage"
  onChange={(value) => console.log('onChange', value)}
  minimum={90}
/>

Allow Negative

Code Editor
<Field.Number allowNegative={false} />

Disallow Leading Zeroes

Code Editor
<Field.Number disallowLeadingZeroes />

Widths

Without step controls

With step controls