Skip to main content
This guide covers changes to the beta DataTable component. These APIs may continue to evolve before the stable release.

Overview

This guide continues the work started in Column Types and EditConfig, which introduced the editConfig property. The boolean edit mode is a new addition that provides a purpose-built editing experience for boolean columns. The DataTable now supports a dedicated boolean edit mode for inline editing of boolean cell values:
  • editConfig.mode: "boolean" - Renders a dropdown menu with predefined true/false options
  • Optional null support - Include a null option for nullable boolean columns
  • Configurable labels - Customize the display text for true, false, and null values
Previously, editable text cells silently coerced boolean values to strings. The new boolean edit mode preserves the boolean type and provides a constrained selection experience.

Design Rationale

Why a dedicated boolean mode?

The text edit mode previously accepted boolean values by converting them to strings:
// Before: Boolean values silently coerced to strings
createColumn("active", {
  headerLabel: "Active",
  editConfig: {
    mode: "text",
    onChange: (value, rowId) => {
      // value is a string — requires manual parsing
      updateActive(value === "true", rowId);
    },
  },
});
This approach had several problems:
  • Values lost their boolean type, requiring manual parsing in onChange
  • Users could type arbitrary text, not just “true” or “false”
  • No constrained selection UX for a binary choice
The new boolean mode addresses all of these:
// After: Purpose-built boolean editing
createColumn("active", {
  headerLabel: "Active",
  type: "boolean",
  editConfig: {
    mode: "boolean",
    trueLabel: "Yes",
    falseLabel: "No",
    onChange: (value, rowId) => {
      // value is boolean | null — no parsing needed
      updateActive(value, rowId);
    },
  },
});

Relationship between type and editConfig

The type property controls how a value is displayed when the cell is not being edited. The editConfig controls the editing behavior. These are independent concerns:
// Display as boolean text, edit with a dropdown
createColumn("active", {
  headerLabel: "Active",
  type: "boolean",                 // Formats display as "True" / "False"
  editConfig: {
    mode: "boolean",               // Edits with a dropdown
    trueLabel: "Enabled",
    falseLabel: "Disabled",
    onChange: handleChange,
  },
});

Label inheritance from type.options

When type is configured with BooleanFormatterOptions (i.e. { type: "boolean", options: { trueLabel, falseLabel } }), the boolean edit mode will automatically use those labels as defaults for the edit dropdown. This avoids duplicating labels across type.options and editConfig:
// "Yes" / "No" labels are used for both display AND the edit dropdown
createColumn("active", {
  headerLabel: "Active",
  type: { type: "boolean", options: { trueLabel: "Yes", falseLabel: "No" } },
  editConfig: {
    mode: "boolean",
    onChange: handleChange,
  },
});
The full priority order for label resolution is:
  1. editConfig.trueLabel / editConfig.falseLabel (explicit override)
  2. type.options.trueLabel / type.options.falseLabel (inherited from formatter config)
  3. "True" / "False" (hardcoded defaults)
This means you can still override individual labels in editConfig when you need different text for the edit dropdown than for the display formatter.

Boolean Edit Options Reference

Boolean-specific options are set directly on the editConfig object alongside mode and onChange. All options are optional.
OptionTypeDefaultDescription
trueLabelstring"True"The label displayed for the true option
falseLabelstring"False"The label displayed for the false option
allowNullbooleanfalseWhether to include a null option in the dropdown
nullLabelstring"Unset"The label displayed for the null option (when allowNull is true)

Basic boolean editing

createColumn("active", {
  headerLabel: "Active",
  type: "boolean",
  editConfig: {
    mode: "boolean",
    onChange: (value, rowId) => updateActive(value, rowId),
  },
});

Custom labels

createColumn("active", {
  headerLabel: "Active",
  type: "boolean",
  editConfig: {
    mode: "boolean",
    trueLabel: "Enabled",
    falseLabel: "Disabled",
    onChange: (value, rowId) => updateActive(value, rowId),
  },
});

Nullable boolean with custom labels

createColumn("approved", {
  headerLabel: "Approved",
  type: "boolean",
  editConfig: {
    mode: "boolean",
    trueLabel: "Approved",
    falseLabel: "Rejected",
    allowNull: true,
    nullLabel: "Pending",
    onChange: (value, rowId) => updateApproval(value, rowId),
  },
});

Migration Guide

Boolean columns using text edit mode

If you were using editMode: "text" or editConfig.mode: "text" for boolean data, switch to boolean mode:
// Before: Text mode with manual boolean handling
createColumn("active", {
  headerLabel: "Active",
  editMode: "text",
  onChange: (value, rowId) => {
    updateActive(value === "true", rowId);
  },
});

// After: Boolean mode with native boolean handling
createColumn("active", {
  headerLabel: "Active",
  type: "boolean",
  editConfig: {
    mode: "boolean",
    onChange: (value, rowId) => updateActive(value ?? false, rowId),
  },
});

Boolean columns using editConfig text mode

// Before: editConfig text mode for booleans
createColumn("active", {
  headerLabel: "Active",
  editConfig: {
    mode: "text",
    onChange: (value, rowId) => updateActive(value === "true", rowId),
  },
});

// After: editConfig boolean mode
createColumn("active", {
  headerLabel: "Active",
  type: "boolean",
  editConfig: {
    mode: "boolean",
    onChange: (value, rowId) => updateActive(value ?? false, rowId),
  },
});

Boolean columns using select edit mode

If you were using mode: "select" to simulate boolean editing with manual options:
// Before: Select mode with manual boolean options
createColumn("active", {
  headerLabel: "Active",
  editConfig: {
    mode: "select",
    options: [
      { value: "true", label: "Yes" },
      { value: "false", label: "No" },
    ],
    onChange: (value, rowId) => updateActive(value === "true", rowId),
  },
});

// After: Boolean mode with configurable labels
createColumn("active", {
  headerLabel: "Active",
  type: "boolean",
  editConfig: {
    mode: "boolean",
    trueLabel: "Yes",
    falseLabel: "No",
    onChange: (value, rowId) => updateActive(value ?? false, rowId),
  },
});

Breaking Changes

The text edit mode no longer coerces boolean values to strings. Columns with boolean data using text edit mode will render as read-only and log a warning.
The following change is breaking:
  • Text edit mode no longer accepts boolean values - Previously, a cell with mode: "text" and a boolean value would silently convert the boolean to a string. Now, the cell falls back to a read-only state and logs a console warning directing you to use mode: "boolean" instead.

Why breaking?

Since DataTable is a beta component, we opted to remove the implicit coercion rather than maintain a deprecation path. The coercion masked type mismatches and produced a suboptimal editing experience for boolean data. The new boolean edit mode is the correct replacement.

New Exports

The following types are now exported from @servicetitan/anvil2:
  • BooleanEditConfig - Edit configuration type for mode: "boolean" columns
Last modified on March 12, 2026