Skip to main content

select Field Type

type: 'select' maps a raw field value to a human-readable label via the options array. The raw value is matched with strict equality (===) against each option's value property. If no match is found, the raw value is displayed as a string.

Core Examples​

Basic Select Rendering​

Status mapped from string values; Priority mapped from numeric values.

Name
Status
Priority
Aurora ChenActiveMedium
Mateo SilvaInactiveLow
Priya NairPendingHigh
{
key: 'status',
label: 'Status',
type: 'select',
options: [
{ value: 'active', label: 'Active' },
{ value: 'inactive', label: 'Inactive' },
{ value: 'pending', label: 'Pending' },
],
},
{
key: 'priority',
label: 'Priority',
type: 'select',
options: [
{ value: 1, label: 'Low' },
{ value: 2, label: 'Medium' },
{ value: 3, label: 'High' },
],
},

Fallback for Unmatched Values​

When no option matches the raw value, the raw value is rendered as a plain string. This makes gaps in your options list immediately visible.

'silver' is not in the options list — Mateo's tier renders as the raw string 'silver'.

Name
Tier (partial options)
Aurora ChenGold
Mateo Silvasilver
Priya NairGold
{
key: 'tier',
label: 'Tier (partial options)',
type: 'select',
options: [
{ value: 'gold', label: 'Gold' },
// 'silver' intentionally omitted — falls back to raw string
],
},

Formatter​

formatter runs before the options lookup. Use it to normalise raw values (e.g. trim whitespace, lowercase) so they reliably match your options.

formatter lowercases and trims the status value before the options lookup fires.

Name
Status (normalised)
Priority
Aurora ChenActiveMedium
Mateo SilvaInactiveLow
Priya NairPendingHigh
{
key: 'status',
label: 'Status (normalised)',
type: 'select',
options: [
{ value: 'active', label: 'Active' },
{ value: 'inactive', label: 'Inactive' },
{ value: 'pending', label: 'Pending' },
],
formatter: (value) => String(value ?? '').toLowerCase().trim(),
},

Condition​

condition receives the full entity and returns true to show the field or false to hide it. Evaluated per row.

Tier column only renders for active users. Mateo (inactive) gets no Tier cell.

Name
Status
Tier (active only)
Aurora ChenActiveGold
Mateo SilvaInactive
Priya NairPending
{
key: 'tier',
label: 'Tier (active only)',
type: 'select',
options: [
{ value: 'gold', label: 'Gold' },
{ value: 'silver', label: 'Silver' },
],
condition: (entity) => entity.status === 'active',
},

Field Options Reference​

OptionTypeDefaultEffect
keystringrequiredEntity property to read the value from.
labelstringunsetColumn header or card label.
type'select'—Maps raw value to a label via options. Falls back to String(value) on no match.
options{ value, label }[]unsetThe lookup table. value can be string, number, or boolean; matched with ===.
formatter(value, entity) => unknownunsetRuns before the options lookup — use to normalise raw values before matching.
condition(entity) => booleanunsetHides the field for rows where the function returns false.
align'left', 'center', 'right''left'Text alignment in table mode.
widthCSS length or numberunsetColumn width in table mode.
showLabeltrue, falsetrue when label is setShows or hides the label in card/grid layouts.
renderAsstringunsetReplace select rendering. Use badge for colour-coded labels.

Caveats​

  • The match is strict (===). A numeric value 1 will not match a string option { value: '1' }.
  • There is no built-in colour or styling on type: 'select'. Use renderAs: 'badge' with a colorMap for visual category indicators.
  • formatter output is what gets matched against options.value — not the original raw value.

Why select vs text + formatter?​

type: 'select' and type: 'text' with a formatter produce identical rendered output today. The distinction is semantic: select declares that a field has a finite, enumerable set of valid values, and the options array is the canonical definition of that set.

Future versions of Widgemo — or add-on packages — may use options to drive:

  • Filter dropdowns that enumerate the known values for a column
  • Inline editing inputs (a <select> element pre-populated with your options)
  • GroupBy controls that label groups using the option labels rather than raw values

Using type: 'select' now means your field config will be forward-compatible with those capabilities without changes. If the field is truly open-ended text, use type: 'text'. If it has a fixed set of values, use type: 'select'.

Performance​

:::tip Stable options reference widgemo-core builds an internal Map from your options array for O(1) lookups. This Map is only rebuilt when the options reference changes. Define your options array outside your render function — or memoize it with useMemo if constructed dynamically — so the Map is reused across renders.

// Good — stable reference, Map built once
const statusOptions = [
{ value: 'active', label: 'Active' },
{ value: 'inactive', label: 'Inactive' },
];

// Avoid — new array every render, Map rebuilt every render
// options={statuses.map(s => ({ value: s.id, label: s.name }))}

:::

See Also​