# Formatting text fields (/docs/guides/tutorials/formatting-text-fields)




Text fields accept any text by default, and the signed PDF prints it at 11 points. When a field needs something more specific, such as a phone number, a dollar amount, or an account number in a fixed shape, you describe that in the field's `config`. Signers see a hint in the empty field and a short message when what they entered doesn't match, and they can't finish until it does.

## Setting a field's config [#setting-a-fields-config]

`config` is part of a template field, so you set it when you [create](/docs/reference/Rest-API/api-docs/fields/createField) or [update](/docs/reference/Rest-API/api-docs/fields/updateField) the field. Envelopes sent from the template copy it along with the rest of the field, and fields you add to an envelope directly (as in [Send an envelope without a template](/docs/guides/tutorials/send-an-envelope-without-a-template)) take the same `config`.

```typescript
import {updateField} from '@verdocs/js-sdk';

await updateField(endpoint, templateId, 'amount', {
  config: {
    type: 'textbox',
    number: {style: 'currency', currency: 'USD', decimals: 2, min: 0},
    fit: {max_font_size: 11, min_font_size: 8, overflow: 'ellipsize'},
  },
});
```

`config.type` always matches the field's type, so you can leave it out and we fill it in. An update replaces the whole `config`, so include every option you want to keep, or send `null` to clear it. The template builder sets the same options from its Inspector panel.

## Built-in formats [#built-in-formats]

The field's `validator` checks for a common format:

| `validator`   | Accepts                                                             |
| ------------- | ------------------------------------------------------------------- |
| `email`       | An email address                                                    |
| `phone`       | A phone number, with or without a country code                      |
| `url`         | A Web address starting with `http://` or `https://`                 |
| `postal_code` | A ZIP or postal code of 3 to 10 letters, digits, spaces, or hyphens |
| `number`      | A number, optionally with thousands separators                      |
| `date`        | A date like `10/27/2026` or `2026-10-27`                            |
| `ssn`         | A Social Security number like `123-45-6789`                         |

A `validator` we don't recognize is treated as plain text.

## Numbers, currency, and percentages [#numbers-currency-and-percentages]

`config.number` makes a field a number field. Signers enter the number the way their locale writes it, and when they leave the field it's rewritten in the field's style. We store the plain number, like `12450.5`, so your integration never has to parse `$12,450.50`, and the signed PDF prints it formatted.

| Option       | Values                                             |
| ------------ | -------------------------------------------------- |
| `style`      | `number`, `currency`, or `percent` (required)      |
| `locale`     | A locale like `de-DE` (defaults to `en-US`)        |
| `currency`   | An ISO 4217 code like `EUR` (defaults to `USD`)    |
| `decimals`   | Decimal places to show, 0 to 6                     |
| `min`, `max` | The smallest and largest number a signer may enter |

| `number`                                                | Signer enters | Stored    | Printed    |
| ------------------------------------------------------- | ------------- | --------- | ---------- |
| `{style: 'currency', currency: 'USD', decimals: 2}`     | `12450.5`     | `12450.5` | $12,450.50 |
| `{style: 'number', locale: 'de-DE', decimals: 2}`       | `12.450,5`    | `12450.5` | 12.450,50  |
| `{style: 'currency', currency: 'EUR', locale: 'fr-FR'}` | `1 234,5`     | `1234.5`  | 1 234,50 € |
| `{style: 'percent'}`                                    | `12.5`        | `12.5`    | 12.5%      |

A number field uses its `number` settings in place of `validator`. To prefill one, send the plain number as a string, like `"12450.5"`.

## Input masks [#input-masks]

`config.input_mask` gives the value a fixed shape. Each `_` is a slot for one character the signer types, and every other character is filled in for them. The mask also shows in the empty field, and the stored value includes the filled-in characters.

```json
{"type": "textbox", "input_mask": "(___) ___-____"}
```

A signer who types `5550123456` gets `(555) 012-3456`, and the field isn't complete until every slot is filled. A slot accepts any character, so pair the mask with a pattern when slots must be digits:

```json
{
  "type": "textbox",
  "input_mask": "(___) ___-____",
  "validation": {"pattern": "\\(\\d{3}\\) \\d{3}-\\d{4}"}
}
```

## Patterns [#patterns]

`config.validation.pattern` is a regular expression the whole value has to match, and `validation.message` is what signers see when it doesn't:

```json
{
  "type": "textbox",
  "validation": {"pattern": "AC-\\d{6}", "message": "Enter your account number, like AC-123456."}
}
```

We match the pattern against the entire value, so you don't need `^` and `$`. Patterns can be up to 500 characters, and we refuse ones that could take too long to match on some values, such as nested repeats like `(a+)+`.

## Text case and length [#text-case-and-length]

`config.text_case` is `upper` or `lower`. Signing converts what the signer types, and we apply it again when a value is saved and when it's stamped, so values your application fills in follow it too. `config.max_length` caps the value at 1 to 10,000 characters.

## Fitting text on the signed PDF [#fitting-text-on-the-signed-pdf]

`config.fit` decides how the value fits the field's width on the signed PDF. Stamping starts at `max_font_size` and steps down toward `min_font_size` until the text fits. Text that's still too wide at the smallest size follows `overflow`.

<img alt="Six samples of text fit settings, from no settings (11 points, running past the field) through shrinking to fit, cutting off, ellipsizing, and a larger 16 point name that already fits." src="__img0" />

| Option          | Values                                                                                                                              |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `max_font_size` | The size stamping starts at, 4 to 72 points (defaults to 11)                                                                        |
| `min_font_size` | The smallest size it shrinks to. Without it, text stays at `max_font_size`.                                                         |
| `overflow`      | `overflow` lets the text run past the field (the default), `truncate` cuts it off, and `ellipsize` cuts it off and ends it with "…" |

In a multi-line field, every line shares the size that fits the widest one. Fit only changes the signed PDF; signers see their full value while they type.

## When several checks apply [#when-several-checks-apply]

Signers see one message at a time, for the first check the value fails: the format or number range, then the mask, then the pattern, then the length. Empty values pass every check, since `required` decides whether a field can be left empty. Read-only fields skip the checks entirely.

## Filling fields from your application [#filling-fields-from-your-application]

When your application fills fields itself, for example in a [proxied signing flow](/docs/guides/tutorials/proxied-signing-flows), we apply `text_case` but store the value without the other checks. js-sdk exports the helpers signing uses, so you can check a value before you send it:

```typescript
import {getFieldFormatProblem, parseFieldNumber} from '@verdocs/js-sdk';

if (field.config?.type === 'textbox' && field.config.number) {
  const amount = parseFieldNumber(field.config.number, '$12,450.50'); // 12450.5
  const problem = getFieldFormatProblem(field, String(amount)); // null when it passes
}
```

A failed check returns `format`, `range`, `mask`, `pattern`, or `length`. `formatFieldNumber` goes the other way, turning a stored number into the text the field shows.
