Skip to content
Backlit
Esc
navigateopen⌘Jpreview
On this page

Number field

Display a number as a count, a decimal, a currency amount, a percentage, or a progress against a total.

This reference explains how to:

  • Declare a finite number
  • Say what the number is with a format
  • Supply a fixed currency code or total, or read one from each record
  • Set an editor step

Overview

A number field declares a finite numeric value. Use a format to say what the number is. The renderer decides how to present it, with the locale supplied by the host. It uses the JavaScript runtime locale when the host does not supply one.

API

fields.number<Name extends string>(
  name: Name,
  options?: NumberFieldOptions
): NumberFieldBuilder<Name>
Option Input Result
label string Sets the text shown for the field.
description string Adds supporting text for the label.
format integer, percent, currency, or progress Says what the number is.
currency An ISO 4217 code, with format: 'currency' Fixes the code for every record.
max number, with format: 'progress' Fixes the total for every record.
displayVariant compact Draws the figure as 12.5K instead of 12,480.
decimals number, with no format, percent, or currency Pins the fraction digits the display shows.
step number Sets the increment used by an editor.

configure(options) returns a configured clone. configure(callback) reads the format’s options from each record. clone() returns an independent copy with the same options.

If you do not set a format, the number is a plain decimal number.

Basic number field

import {
  datalist,
  defineResource,
  fields,
} from '@backlit/sdk'

const products = defineResource('products', [
  fields.number('stock', { label: 'Stock' }),
])

products.view('detail', () =>
  datalist({ stock: 128 }).setFields(products.pick('stock'))
)

export default products
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "products",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "datalist",
          "fields": [
            {
              "kind": "number",
              "name": "stock",
              "label": "Stock"
            }
          ],
          "data": {
            "stock": 128
          }
        }
      ]
    }
  }
}

Description

Use a description when the value needs a unit, rule, or other supporting information that does not belong in the label.

import {
  datalist,
  defineResource,
  fields,
} from '@backlit/sdk'

const products = defineResource('products', [
  fields.number('reorderAt', {
    label: 'Reorder at',
    description:
      'Create a purchase order when stock reaches this value.',
  }),
])

products.view('detail', () =>
  datalist({ reorderAt: 20 }).setFields(
    products.pick('reorderAt')
  )
)

export default products
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "products",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "datalist",
          "fields": [
            {
              "kind": "number",
              "name": "reorderAt",
              "description": "Create a purchase order when stock reaches this value.",
              "label": "Reorder at"
            }
          ],
          "data": {
            "reorderAt": 20
          }
        }
      ]
    }
  }
}

Formats

Number supports four formats. A format says what the number is. A fixed format sends a number. Per-record currency or progress options send an object with value and the resolved currency or max.

Format Use Options
integer A whole count.
percent A fraction, where 0.15 represents 15 percent.
currency An amount of money. currency
progress A count against a total, drawn as a bar with the share. max

An option is accepted only with its format. A format’s option is fixed for every record when you set it on the field, or read from each record through a callback:

import { fields } from '@backlit/sdk'

const price = fields.number('price', {
  format: 'currency',
  currency: 'USD',
})

const convertedPrice = fields
  .number('convertedPrice', { format: 'currency' })
  .configure((row: { currencyCode: string }) => ({
    currency: row.currencyCode,
  }))

const shipped = fields
  .number('shipped', { format: 'progress' })
  .configure((row: { ordered: number }) => ({ max: row.ordered }))

A code must contain three uppercase letters, such as USD, EUR, or BRL. A total must be a finite number of zero or more. Backlit reports a defect when a record supplies an invalid value, or supplies an option for a format the field does not declare. A progress with no total draws the count alone.

import {
  datalist,
  defineResource,
  fields,
} from '@backlit/sdk'

const products = defineResource('products', [
  fields.number('stock', {
    label: 'Stock',
    format: 'integer',
  }),
  fields.number('weight', {
    // No format: a plain decimal number.
    label: 'Weight',
  }),
  fields.number('price', {
    label: 'Price',
    format: 'currency',
    currency: 'USD',
  }),
  fields
    .number('convertedPrice', {
      label: 'Converted price',
      format: 'currency',
    })
    // A code the field does not carry comes from each record.
    .configure((row: { currencyCode: string }) => ({
      currency: row.currencyCode,
    })),
  fields.number('discount', {
    label: 'Discount',
    format: 'percent',
  }),
  fields.number('shipped', {
    label: 'Shipped',
    format: 'progress',
    max: 240,
  }),
])

products.view('detail', () =>
  datalist({
    stock: 128,
    weight: 1.25,
    price: 149.5,
    convertedPrice: 139.5,
    currencyCode: 'EUR',
    discount: 0.15,
    shipped: 96,
  }).setFields(
    products.pick(
      'stock',
      'weight',
      'price',
      'convertedPrice',
      'discount',
      'shipped'
    )
  )
)

export default products
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "products",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "datalist",
          "fields": [
            {
              "kind": "number",
              "name": "stock",
              "format": "integer",
              "label": "Stock"
            },
            {
              "kind": "number",
              "name": "weight",
              "label": "Weight"
            },
            {
              "kind": "number",
              "name": "price",
              "format": "currency",
              "currency": "USD",
              "label": "Price"
            },
            {
              "kind": "number",
              "name": "convertedPrice",
              "format": "currency",
              "label": "Converted price"
            },
            {
              "kind": "number",
              "name": "discount",
              "format": "percent",
              "label": "Discount"
            },
            {
              "kind": "number",
              "name": "shipped",
              "format": "progress",
              "max": 240,
              "label": "Shipped"
            }
          ],
          "data": {
            "stock": 128,
            "weight": 1.25,
            "price": 149.5,
            "convertedPrice": {
              "value": 139.5,
              "currency": "EUR"
            },
            "discount": 0.15,
            "shipped": 96
          }
        }
      ]
    }
  }
}

Decimals

A currency strips its fraction when the amount is whole and keeps it otherwise: 1200 shows as $1,200, and 1200.5 as $1,200.50. An integer and a progress count show no fraction. A percent shows at most one decimal.

Set decimals to pin the fraction of a plain number, a percent, or a currency. An integer and a progress count have no fraction and do not take it. decimals: 2 shows two digits on every value. decimals: 0 rounds to a whole number: 412222.89 shows as $412,223.

import { fields } from '@backlit/sdk'

const total = fields.number('total', {
  format: 'currency',
  currency: 'USD',
  decimals: 2,
})

Compact figures

The compact display variant draws a figure in the locale’s compact notation with at most one decimal: 12,480 as 12.5K, 1,200,000 as 1.2M. It composes with any format. A compact currency keeps its symbol, and a compact progress draws both counts compact.

import { fields } from '@backlit/sdk'

const subscribers = fields.number('subscribers', {
  format: 'integer',
  displayVariant: 'compact',
})

Step

The step tells an editing control how much to add or subtract for one change. When you do not set it, a field with decimals steps by that unit, one for zero and a hundredth for two, and an integer field steps by one. The step does not change the read-only value.

import {
  datalist,
  defineResource,
  fields,
} from '@backlit/sdk'

const products = defineResource('products', [
  fields.number('quantity', {
    label: 'Quantity',
    format: 'integer',
    step: 5,
  }),
])

products.view('detail', () =>
  datalist({ quantity: 25 }).setFields(
    products.pick('quantity')
  )
)

export default products
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "products",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "datalist",
          "fields": [
            {
              "kind": "number",
              "name": "quantity",
              "format": "integer",
              "step": 5,
              "label": "Quantity"
            }
          ],
          "data": {
            "quantity": 25
          }
        }
      ]
    }
  }
}

Clone

Use configure to reuse a number field with different options. It does not change the source field.

import {
  datalist,
  defineResource,
  fields,
} from '@backlit/sdk'

const price = fields.number('price', {
  label: 'Price',
})
const products = defineResource('products', [
  price.configure({
    format: 'currency',
    currency: 'USD',
  }),
])

products.view('detail', () =>
  datalist({ price: 149.5 }).setFields(
    products.pick('price')
  )
)

export default products
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "products",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "datalist",
          "fields": [
            {
              "kind": "number",
              "name": "price",
              "format": "currency",
              "currency": "USD",
              "label": "Price"
            }
          ],
          "data": {
            "price": 149.5
          }
        }
      ]
    }
  }
}

All options

You can use a label, description, format, and step on the same number field.

import {
  datalist,
  defineResource,
  fields,
} from '@backlit/sdk'

const products = defineResource('products', [
  fields.number('price', {
    label: 'Price',
    description: 'The current price before tax.',
    format: 'currency',
    currency: 'USD',
    step: 0.01,
  }),
])

products.view('detail', () =>
  datalist({ price: 149.5 }).setFields(
    products.pick('price')
  )
)

export default products
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "products",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "datalist",
          "fields": [
            {
              "kind": "number",
              "name": "price",
              "description": "The current price before tax.",
              "format": "currency",
              "currency": "USD",
              "step": 0.01,
              "label": "Price"
            }
          ],
          "data": {
            "price": 149.5
          }
        }
      ]
    }
  }
}

Was this page helpful?