Data & Editing

Cell Data Types

Use built-in cell types for common data formats.

NuGrid provides built-in cell data types that handle formatting, display, and editing for common data formats.

Different cell data types provide appropriate editors: text input, number input, date picker, and checkbox.

ID
Name
Price
Release Date
In Stock
1
Laptop
$1299.99
1/15/2024
2
Mouse
$29.99
6/10/2023
3
Cable
$12.99
3/22/2023
4
Monitor
$599.99
8/5/2024
<script setup lang="ts">
import type { NuGridColumn } from '#nu-grid/types'

interface Product {
  id: number
  name: string
  price: number
  releaseDate: string
  inStock: boolean
}

const data = ref<Product[]>([
  { id: 1, name: 'Laptop', price: 1299.99, releaseDate: '2024-01-15', inStock: true },
  { id: 2, name: 'Mouse', price: 29.99, releaseDate: '2023-06-10', inStock: true },
  { id: 3, name: 'Cable', price: 12.99, releaseDate: '2023-03-22', inStock: false },
  { id: 4, name: 'Monitor', price: 599.99, releaseDate: '2024-08-05', inStock: true },
])

const columns: NuGridColumn<Product>[] = [
  { accessorKey: 'id', header: 'ID', size: 60, enableEditing: false, cellDataType: 'number' },
  { accessorKey: 'name', header: 'Name', size: 120, cellDataType: 'text' },
  {
    accessorKey: 'price',
    header: 'Price',
    size: 100,
    cellDataType: 'number',
    cell: ({ row }) => `$${row.original.price.toFixed(2)}`,
  },
  {
    accessorKey: 'releaseDate',
    header: 'Release Date',
    size: 130,
    cellDataType: 'date',
    cell: ({ row }) => new Date(row.original.releaseDate).toLocaleDateString(),
  },
  { accessorKey: 'inStock', header: 'In Stock', size: 100, cellDataType: 'boolean' },
]

const toast = useToast()

function onCellValueChanged(event: { row: any; column: any; oldValue: any; newValue: any }) {
  toast.add({
    title: 'Cell Updated',
    description: `${event.column.id}: "${event.oldValue}" → "${event.newValue}"`,
    color: 'success',
  })
}
</script>

<template>
  <div class="w-full">
    <p class="mb-3 text-sm text-muted">
      Different cell data types provide appropriate editors: text input, number input, date picker,
      and checkbox.
    </p>
    <NuGrid
      :data="data"
      :columns="columns"
      :editing="{ enabled: true, startClicks: 'double' }"
      :ui="{
        base: 'w-full border-separate border-spacing-0',
        thead: '[&>tr]:bg-elevated/50',
        th: 'py-2 border-y border-default first:border-l last:border-r first:rounded-l-lg last:rounded-r-lg',
        td: 'border-b border-default',
      }"
      @cell-value-changed="onCellValueChanged"
    />
  </div>
</template>

Automatic Type Inference

NuGrid automatically infers data types from your row data, similar to AG Grid. This means you often don't need to manually specify cellDataType for each column.

How It Works

When data is loaded, NuGrid examines the values in each column and detects the appropriate type:

Detected TypeDetection Logic
booleanValues are true or false
dateValues are JavaScript Date objects
currencyString with currency symbol ($123.45) OR number with 2 decimals + column name contains price/cost/amount/total/fee/salary/etc.
percentageString with percent sign (45%) OR number 0-1 + column name contains percent/rate/ratio
numberNumeric values
textDefault fallback for strings

Example

// No cellDataType needed - types are inferred automatically!
const columns = [
  { accessorKey: 'name', header: 'Name' },           // Inferred: 'text'
  { accessorKey: 'price', header: 'Price' },         // Inferred: 'currency' (2 decimals + "price")
  { accessorKey: 'discountRate', header: 'Rate' },   // Inferred: 'percentage' (0-1 + "rate")
  { accessorKey: 'inStock', header: 'In Stock' },    // Inferred: 'boolean'
  { accessorKey: 'orderDate', header: 'Date' },      // Inferred: 'date' (Date object)
]

const data = [
  {
    name: 'Laptop',
    price: 1299.99,          // Currency: 2 decimals + column name
    discountRate: 0.15,      // Percentage: 0-1 + column name
    inStock: true,           // Boolean
    orderDate: new Date(),   // Date object
  },
]

Disabling Type Inference

Globally: Set dataTypeInference to false on the grid:

<NuGrid
  :data="data"
  :columns="columns"
  :data-type-inference="false"
/>

Per column: Set cellDataType to false to disable inference for that column:

{
  accessorKey: 'price',
  header: 'Price',
  cellDataType: false,  // No inference, use default text rendering
}

Explicit type: Setting any cellDataType value prevents inference for that column:

{
  accessorKey: 'amount',
  header: 'Amount',
  cellDataType: 'number',  // Use number, not currency
}

Available Cell Types

TypeDescriptionDisplayEditor
textPlain textTextText input
numberNumeric valuesFormatted numberNumber input
currencyMoney valuesCurrency formatNumber input
percentagePercentage valuesFormatted with %Number input with %
booleanTrue/false valuesCheckboxCheckbox
dateDate valuesFormatted dateDate picker
ratingStar ratingsStarsStar selector
selectionSelect from optionsSelected valueDropdown
lookupLookup valuesResolved valueLookup picker
action-menuRow actionsAction buttonMenu

Using Cell Data Types

Specify the cellDataType on a column:

const columns: NuGridColumn<Product>[] = [
  { accessorKey: 'name', header: 'Name', cellDataType: 'text' },
  { accessorKey: 'price', header: 'Price', cellDataType: 'currency' },
  { accessorKey: 'quantity', header: 'Qty', cellDataType: 'number' },
  { accessorKey: 'active', header: 'Active', cellDataType: 'boolean' },
  { accessorKey: 'createdAt', header: 'Created', cellDataType: 'date' },
]

Text

Plain text display and editing:

{
  accessorKey: 'name',
  header: 'Name',
  cellDataType: 'text',
}

Number

Numeric values with formatting:

{
  accessorKey: 'quantity',
  header: 'Quantity',
  cellDataType: 'number',
  cellDataTypeOptions: {
    locale: 'en-US',
    minimumFractionDigits: 0,
    maximumFractionDigits: 2,
  },
}

Currency

Money values with currency formatting:

{
  accessorKey: 'price',
  header: 'Price',
  cellDataType: 'currency',
  cellDataTypeOptions: {
    currency: 'USD',
    locale: 'en-US',
  },
}

Currency Options

OptionTypeDefaultDescription
currencystring'USD'Currency code
localestring'en-US'Locale for formatting

Percentage

Percentage values with % formatting:

{
  accessorKey: 'discountRate',
  header: 'Discount',
  cellDataType: 'percentage',
}

Storage Modes

Percentages can be stored as decimals (0-1) or as whole numbers (0-100):

// Stored as decimal (0.15 displays as "15.0%")
{
  accessorKey: 'rate',
  cellDataType: 'percentage',
  percentageStorage: 'decimal',  // Default
}

// Stored as whole number (15 displays as "15.0%")
{
  accessorKey: 'rate',
  cellDataType: 'percentage',
  percentageStorage: 'percent',
}

Percentage Options

OptionTypeDefaultDescription
percentageStorage'decimal' | 'percent''decimal'How values are stored
percentageDecimalsnumber1Decimal places to display

Boolean

Checkbox display and editing:

{
  accessorKey: 'active',
  header: 'Active',
  cellDataType: 'boolean',
}

Boolean cells render as checkboxes and toggle on click or space key.

Date

Date display with formatting:

{
  accessorKey: 'createdAt',
  header: 'Created',
  cellDataType: 'date',
  cellDataTypeOptions: {
    format: 'MMM dd, yyyy',
    locale: 'en-US',
  },
}

Date Options

OptionTypeDefaultDescription
formatstring'PP'Date format string
localestringSystem localeLocale for formatting

Rating

Star rating display:

{
  accessorKey: 'rating',
  header: 'Rating',
  cellDataType: 'rating',
  cellDataTypeOptions: {
    max: 5,
    color: 'yellow',
  },
}

Rating Options

OptionTypeDefaultDescription
maxnumber5Maximum rating value
colorstring'yellow'Star color

Selection

Dropdown selection from predefined options:

{
  accessorKey: 'status',
  header: 'Status',
  cellDataType: 'selection',
  cellDataTypeOptions: {
    options: [
      { label: 'Active', value: 'active' },
      { label: 'Pending', value: 'pending' },
      { label: 'Inactive', value: 'inactive' },
    ],
  },
}

Or with simple string array:

{
  accessorKey: 'category',
  header: 'Category',
  cellDataType: 'selection',
  cellDataTypeOptions: {
    options: ['Electronics', 'Clothing', 'Food', 'Other'],
  },
}

Selection Options

OptionTypeDescription
optionsstring[] | { label, value }[]Available options
placeholderstringPlaceholder text
searchablebooleanEnable search

Lookup

Lookup values from a reference dataset:

const users = ref([
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Carol' },
])

const columns = [
  {
    accessorKey: 'assigneeId',
    header: 'Assignee',
    cellDataType: 'lookup',
    cellDataTypeOptions: {
      options: users,
      labelKey: 'name',
      valueKey: 'id',
    },
  },
]

Lookup Options

OptionTypeDescription
optionsRef<any[]> | any[]Lookup data source
labelKeystringKey for display label
valueKeystringKey for value
searchablebooleanEnable search

Action Menu

Add row actions menu:

{
  id: 'actions',
  header: 'Actions',
  cellDataType: 'action-menu',
}

See Row Actions for complete action menu documentation.

Custom Cell Renderers

Override the default renderer while keeping the data type:

{
  accessorKey: 'status',
  header: 'Status',
  cellDataType: 'selection',
  cellDataTypeOptions: {
    options: ['active', 'pending', 'inactive'],
  },
  // Custom display while keeping selection editor
  cell: ({ row }) => {
    const colors = {
      active: 'success',
      pending: 'warning',
      inactive: 'error',
    }
    return h(UBadge, {
      color: colors[row.original.status],
      label: row.original.status,
    })
  },
}

Registering Custom Cell Types

Create custom cell types using the cell type registry:

// plugins/custom-cell-types.ts
import { useNuGridCellTypeRegistry } from '#nu-grid'

export default defineNuxtPlugin(() => {
  const registry = useNuGridCellTypeRegistry()

  registry.register('percentage', {
    display: ({ value }) => `${(value * 100).toFixed(1)}%`,
    editor: defineComponent({
      // Custom editor component
    }),
  })
})

Then use it:

{
  accessorKey: 'completion',
  header: 'Progress',
  cellDataType: 'percentage',
}

Example: Multiple Data Types

<script setup lang="ts">
interface Product {
  id: number
  name: string
  category: string
  price: number
  stock: number
  active: boolean
  rating: number
  createdAt: Date
}

const columns: NuGridColumn<Product>[] = [
  {
    accessorKey: 'name',
    header: 'Name',
    cellDataType: 'text',
  },
  {
    accessorKey: 'category',
    header: 'Category',
    cellDataType: 'selection',
    cellDataTypeOptions: {
      options: ['Electronics', 'Clothing', 'Food', 'Home'],
    },
  },
  {
    accessorKey: 'price',
    header: 'Price',
    cellDataType: 'currency',
    cellDataTypeOptions: { currency: 'USD' },
  },
  {
    accessorKey: 'stock',
    header: 'Stock',
    cellDataType: 'number',
  },
  {
    accessorKey: 'active',
    header: 'Active',
    cellDataType: 'boolean',
  },
  {
    accessorKey: 'rating',
    header: 'Rating',
    cellDataType: 'rating',
    cellDataTypeOptions: { max: 5 },
  },
  {
    accessorKey: 'createdAt',
    header: 'Created',
    cellDataType: 'date',
    cellDataTypeOptions: { format: 'PP' },
  },
]
</script>

<template>
  <NuGrid
    :data="data"
    :columns="columns"
    :editing="{ enabled: true }"
  />
</template>

Next Steps

Cell Editing

Enable inline cell editing.

Validation

Validate cell values.