# NumberField

> NumberField is a text field for an int or a double with an optional range, built-in errors for bad input and an optional extra validator.

URL: https://xichil.dev/docs/xis-mvui/v1/widgets/number-field/ · Updated: 2026-11-06 · Applies to: Fabric, Quilt, Legacy Fabric, Forge, NeoForge, MC 1.7.10 - 26.3

A [TextInput](https://xichil.dev/docs/xis-mvui/v1/widgets/text-input/index.md) for a number, optionally between a minimum and a maximum. Use it where the player
types an exact number (a port, a seed, a radius); for a value the player drags, use a [Slider](https://xichil.dev/docs/xis-mvui/v1/widgets/slider/index.md).

```java
NumberField.ofInt("radius")
        .label(Text.translatable("mymod.radius", "Radius (blocks)"))
        .initial(config.radius)
        .range(1, 256)
        .onChange(r -> config.radius = r)
        .build();

NumberField.ofDouble("scale")
        .label(Text.translatable("mymod.scale", "Scale"))
        .initial(config.scale)
        .range(0.1, null)                       // no upper bound
        .onChange(s -> config.scale = s)
        .build();
```

## Builder

Start with `NumberField.ofInt(id)` (whole numbers, `Integer`) or `NumberField.ofDouble(id)` (`Double`).

| Method | Required | Default | Notes |
| --- | --- | --- | --- |
| `label(Supplier<Text>)` / `label(Text)` | yes | | the text above the field |
| `initial(N)` | yes | | the starting number, usually your current value. Shown without trailing zeros; not checked against the range or passed to `onChange`. |
| `onChange(Consumer<? super N>)` | yes | | receives the number after each edit that leaves the text valid; main thread |
| `range(N min, N max)` | no | unbounded (`ofInt`: the `int` range) | both inclusive; either may be `null` for no bound |
| `maxLength(int)` | no | `32` | the most characters the field accepts |
| `validator(Function<? super N, Text>)` | no | none | an extra check; returns an error or `null`. Runs last, only on in-range numbers. |
| `enabled`, `tooltip`, `visible` | no | | [options every widget has](https://xichil.dev/docs/xis-mvui/v1/widgets/index.md#options-every-widget-has) |

`build()` throws if a required field is missing, a number is NaN or infinite, `min > max`, or `maxLength` isn't
positive.

## Built-in errors

| Input | Error below the field |
| --- | --- |
| empty, or not a number | Not a number |
| a decimal in an `ofInt` field (`2.5`; `2.0` counts as 2) | Not a whole number |
| below the minimum | Must be at least *min* |
| above the maximum | Must be at most *max* |

The text is trimmed and parsed with `.` as the decimal separator in every language; `1e3` is accepted.

## Methods

| Method | Gives |
| --- | --- |
| `number()` | the number in the field, for an action that reads it directly |
| `input()` | the `TextInput` it is drawn as: `input().value()` is the text, `input().isValid()` whether it's valid |
| `min()`, `max()` | the bounds, or `null` |

## Behaviour

- As with a text input, the typed text lives in the entry and survives refreshes; `onChange` only sees valid
  numbers ([Validate what players type](https://xichil.dev/docs/xis-mvui/v1/guides/validation/index.md)).
- **Footer:** yes.

## Test it

```java
host.type("radius", "300");
assertTrue(host.render().contains("(error: Must be at most 256)"));
```

Rendered as `[input radius] Radius (blocks): "300" (error: Must be at most 256)`.

## See also

- Javadoc: [NumberField](https://xichil.dev/javadoc/xis-mvui/v1/dev/xichil/mvui/NumberField.html)
