Skip to content

Field Formatting — cdx_field_formatting

cdx_field_formatting is a singleton dispatch registry for formatting field values. Every CDX surface that renders a date, number, currency, duration, or formatted JSON reads from the same FieldFormatter.instance — so changing the locale, date pattern, or timezone in one place re-formats every value in the app.

dart
import 'package:cdx_field_formatting/cdx_field_formatting.dart';

FieldFormatter

The singleton is populated synchronously on first access — no async initialization. The registry, timezone data, and built-in formatters are wired immediately.

dart
// Typed convenience
FieldFormatter.instance.formatDate(area.createdAt);
FieldFormatter.instance.formatDateTime(area.updatedAt);
FieldFormatter.instance.formatTime(shift.startedAt);
FieldFormatter.instance.formatNumber(123456.789);
FieldFormatter.instance.formatInt(42);
FieldFormatter.instance.formatPercent(0.875);          // 87.50%
FieldFormatter.instance.formatCurrency(42.5, 'USD');
FieldFormatter.instance.formatBytes(1234567);          // 1.18 MB
FieldFormatter.instance.formatDuration(const Duration(minutes: 90));
FieldFormatter.instance.formatPhone('+15551234567');
FieldFormatter.instance.formatBool(true);

// Field-name dispatch — uses aliases / regex patterns / runtime-type fallback
FieldFormatter.instance.formatField('created_at', area.createdAt);   // /_at$/ → datetime
FieldFormatter.instance.formatField('is_active', true);              // /^is_/ → bool
FieldFormatter.instance.formatField('size_diameter', 12.5);          // /^size_/ → decimal

// Widget version (Map / List → JsonConfigFormatter chip; DateTime → FormattedDateTime)
FieldFormatter.instance.formatFieldWidget(context, 'config', task.config);

Settings — FormatSettings

FormatSettings is a reactive value (MobX Observable). Any widget inside an Observer that calls a format method auto-rebuilds when updateSettings is called.

dart
FieldFormatter.instance.updateSettings(FormatSettings(
  locale: 'en-US',
  dateFormat: 'MMM d, y',
  dateTimeFormat: 'MMM d, y h:mm a',
  timeFormat: 'h:mm a',
  timezone: 'America/Chicago',
  currency: 'USD',
  // ...
));

// Reset to FormatSettings.defaults
FieldFormatter.instance.reset();

Custom registrations

dart
// Register a custom formatter for a tag
FieldFormatter.instance.register<MyEnum>('my_enum', const MyEnumFormatter());

// Alias a field name to a tag
FieldFormatter.instance.aliasField('priority', 'my_enum');

// Bulk alias many fields at once
FieldFormatter.instance.aliasFields({
  'priority': 'my_enum',
  'severity': 'my_enum',
});

// Register a regex pattern (first match wins; checked when no exact alias exists)
FieldFormatter.instance.registerFieldPattern(RegExp(r'_email$'), FieldType.email.tag);

// Widget-producing formatter (for status chips, icons, etc.)
FieldFormatter.instance.registerWidget<bool>(
  'bool_active',
  const BoolChipFormatter(),
);

Built-in field-name patterns

Auto-resolved when no exact alias exists:

PatternTag
_at$datetime
_on$ / _date$date
_time$time
^last_datetime
^next_date
_by$user_id
_count$ / _size$ / _quantity$ / _qty$ / _number$integer
^size_decimal
_percent$ / _percentage$percent
^is_ / ^has_bool

FieldType tags

Built-in tags exposed as an enum so callers can avoid magic strings.

dart
enum FieldType {
  text, date, dateTime, dateRelative, time, dateLong,
  boolean, booleanActive, integer, decimal, number,
  currency, percentage, bytes, duration, phone,
  email, url, uuid, userId, entityId, json, list,
}

// Use the .tag string when registering / aliasing
FieldFormatter.instance.aliasField('email_address', FieldType.email.tag);

Named formatter constants

DateFormatters.standard, NumberFormatters.percent(), etc., are preconfigured Formatter<T> instances exposed via abstract holder classes. Pass them to typed convenience methods to override the default:

dart
FieldFormatter.instance.formatDate(dt, format: DateFormatters.long);          // April 18, 2026
FieldFormatter.instance.formatDate(dt, format: DateFormatters.relative);      // 5 minutes ago
FieldFormatter.instance.formatDate(dt, format: DateFormatters.pattern('yyyy/MM/dd'));
FieldFormatter.instance.formatNumber(n, format: NumberFormatters.compact);    // 1.2K
FieldFormatter.instance.formatCurrency(n, 'USD', format: CurrencyFormatters.accounting); // (42.50)
HolderNotable members
DateFormattersstandard, dateTime, time, long, medium, short, relative, dayOfWeek, monthYear, iso, pattern(...)
NumberFormattersstandard, integer, percent({fractionDigits}), compact(), pattern(...)
CurrencyFormattersstandard, compact, accounting
BooleanFormattersstandard
BytesFormattersstandard
DurationFormattersstandard
PhoneFormattersstandard

Widget-producing formatters

ClassRenders
FormattedDateTime / FormattedDateTimeFormatterAdaptive date/time block — stacked date+time on narrow, inline on wide
BoolChipFormatterStatus chip for active/inactive booleans
IconValueFormatter<T>Icon + value (used for typed enums)
JsonConfigFormatterCompact "View JSON" chip with a tap-to-open pretty-printed dialog (default fallback for Map/List in formatFieldWidget)

Locale loading

For non-default locales, call once at startup:

dart
await FieldFormatter.instance.loadLocales(['en-US', 'de-DE', 'hi-IN']);
  • State Views — surface-level usage
  • PickersCdxDateRangePicker formats trigger label via FieldFormatter.instance.formatDate