Skip to content

Formatters

Clean up input as the user types — phone masks, currency decimals, URL slugs.

Previous: Calculations · Next: Integrations

Playground

Formatters explorer → — compare display value vs stored value.

Problem → solution

ProblemSolution
Mask / normalize in every input handlerField format / parse options
Display value ≠ stored valueBuilt-in formatters (phone, currency, slug, …)

Overview

Formatters run on setValue and normalize stored values. They are separate from validators (validity checks).

ts
import { phone, currency, slug } from "@jayoncode/form-intelligent";

form.field("phone", { format: phone }).setValue("5551234567");
// stored: "(555) 123-4567"

Built-in formatters

FormatterExample in → stored
phone5551234567(555) 123-4567
currency42.542.50
creditCard41111111111111114111 1111 1111 1111
slugHello World!hello-world
trim / uppercase / lowercaseString cleanup
ts
import {
  phone,
  currency,
  slug,
  creditCard,
  creditCardParser,
} from "@jayoncode/form-intelligent/format";

form.field("amount", { format: currency }).setValue(rawInput);
form.field("handle", { format: slug }).setValue(title);
form.field("card", { format: creditCard, parse: creditCardParser }).setValue(input);

Format vs parse

HookWhenUse for
parseOn input (before format)Strip mask characters
formatOn display / storeDisplay normalization

Toggle with parseOnInput / formatOnDisplay on field options.

ts
form.field("code", {
  parse: (v) => String(v).replace(/\s/g, ""),
  format: (v) => String(v).toUpperCase(),
});

Compose chains:

ts
import { composeFormatters, trim, uppercase } from "@jayoncode/form-intelligent/format";

form.field("code", { format: composeFormatters(trim, uppercase) });

Custom formatter

ts
import { custom } from "@jayoncode/form-intelligent/format";

const definition = custom(
  (value) => String(value).toUpperCase(),
  (value) => String(value).trim(),
);

form.field("code", definition);

Schema presets: format: "philippine-phone" | "credit-card" | "phone" | "currency" | "slug".


Element structure

Native HTML

html
<form id="profile">
  <label>
    Phone
    <input name="phone" inputmode="tel" autocomplete="tel" />
  </label>
  <label>
    Card
    <input name="card" inputmode="numeric" autocomplete="cc-number" />
  </label>
</form>
ts
createForm({
  target: "#profile",
  schema: {
    phone: { format: "philippine-phone" },
    card: { format: "credit-card" },
  },
});

React JSX

tsx
<label>
  Phone
  <input
    {...form.field("phone")}
    onChange={(event) => {
      form.field("phone", { format: phone }).setValue(event.target.value);
    }}
    inputMode="tel"
  />
</label>

Or rely on schema presets / field options registered once at create time, then {...form.field("phone")} alone is enough.

Next: Integrations — session, keyboard, analytics.

JOC is a JayOnCode monorepo of @jayoncode/* packages. Docs sync from source via TypeDoc and sync scripts.