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
}
}
]
}
}
}