Ref field
Display records that the current record points to.
A Ref field represents a forward relation, such as an order that points to a customer. The declaration identifies the target resource and the field that displays each related record.
API
fields.ref(
name,
() => resource,
options: RefFieldOptions & { display: string | FieldBuilder }
)
| Option | Input | Result |
|---|---|---|
display |
string, field builder |
Displays through a target resource field. |
label |
string |
Sets the text shown for the field. |
description |
string |
Adds supporting text for the label. |
inputVariant |
lookup input variant | Selects a related value through a lookup. |
cardinality |
one, many |
Selects one related value or an array. |
configure(options) returns a configured clone. clone() returns an
independent copy with the same target declaration and options. configure can replace the display field. The target resource stays fixed.
The target resource function is a type-safe authoring reference. The protocol sends the complete display field.
Basic Ref field
The related record is read through its declared display field.
import {
datalist,
defineResource,
fields,
} from '@backlit/sdk'
import { categories } from './categories.ts'
const products = defineResource('products', [
fields.ref('category', () => categories, {
label: 'Category',
display: 'name',
}),
])
products.view('detail', () =>
datalist({ category: { name: 'Lighting' } }).setFields(
products.pick('category')
)
)
export default productsimport { defineResource, fields } from '@backlit/sdk'
export const categories = defineResource('categories', [
fields.text('name'),
]){
"kind": "success",
"status": 200,
"node": {
"kind": "view",
"resource": "products",
"name": "detail",
"slots": {
"content": [
{
"kind": "datalist",
"fields": [
{
"kind": "ref",
"name": "category",
"label": "Category",
"display": {
"kind": "text",
"name": "name",
"label": ""
}
}
],
"data": {
"category": "Lighting"
}
}
]
}
}
}Related record
Pass the related record. The display field reads and converts its value.
import {
datalist,
defineResource,
fields,
} from '@backlit/sdk'
import { categories } from './categories.ts'
const products = defineResource('products', [
fields.ref('category', () => categories, {
label: 'Category',
display: 'name',
}),
])
products.view('detail', () =>
datalist({
category: {
id: 7,
name: 'Lighting',
internalCode: 'CAT-7',
},
}).setFields(products.pick('category'))
)
export default productsimport { defineResource, fields } from '@backlit/sdk'
export const categories = defineResource('categories', [
fields.number('id'),
fields.text('name'),
]){
"kind": "success",
"status": 200,
"node": {
"kind": "view",
"resource": "products",
"name": "detail",
"slots": {
"content": [
{
"kind": "datalist",
"fields": [
{
"kind": "ref",
"name": "category",
"label": "Category",
"display": {
"kind": "text",
"name": "name",
"label": ""
}
}
],
"data": {
"category": "Lighting"
}
}
]
}
}
}Description
import {
datalist,
defineResource,
fields,
} from '@backlit/sdk'
import { categories } from './categories.ts'
const products = defineResource('products', [
fields.ref('category', () => categories, {
label: 'Category',
display: 'name',
description:
'The catalogue group that owns this product.',
}),
])
products.view('detail', () =>
datalist({ category: { name: 'Lighting' } }).setFields(
products.pick('category')
)
)
export default productsimport { defineResource, fields } from '@backlit/sdk'
export const categories = defineResource('categories', [
fields.text('name'),
]){
"kind": "success",
"status": 200,
"node": {
"kind": "view",
"resource": "products",
"name": "detail",
"slots": {
"content": [
{
"kind": "datalist",
"fields": [
{
"kind": "ref",
"name": "category",
"description": "The catalogue group that owns this product.",
"label": "Category",
"display": {
"kind": "text",
"name": "name",
"label": ""
}
}
],
"data": {
"category": "Lighting"
}
}
]
}
}
}Display link
Configure the display field with link. The related record must contain every
value that its field and link args callback use.
import {
datalist,
defineResource,
fields,
linkTo,
} from '@backlit/sdk'
import { categories, categoryDetail } from './categories.ts'
const products = defineResource('products', [
fields.ref('category', () => categories, {
display: fields.text('name').configure({
link: linkTo(
() => categoryDetail,
(record: { id: number }) => [record.id]
),
}),
label: 'Category',
}),
])
products.view('detail', () =>
datalist({
category: { id: 7, name: 'Lighting' },
}).setFields(products.pick('category'))
)
export default productsimport { defineResource, fields } from '@backlit/sdk'
export const categories = defineResource('categories', [
fields.number('id'),
fields.text('name'),
])
export const categoryDetail = categories.view(
'detail',
['id'],
() => []
){
"kind": "success",
"status": 200,
"node": {
"kind": "view",
"resource": "products",
"name": "detail",
"slots": {
"content": [
{
"kind": "datalist",
"fields": [
{
"kind": "ref",
"name": "category",
"label": "Category",
"display": {
"kind": "text",
"name": "name",
"label": "",
"link": {
"kind": "link",
"resource": "categories",
"view": "detail"
}
}
}
],
"data": {
"category": {
"value": "Lighting",
"args": [
7
]
}
}
}
]
}
}
}Lookup input variant
Use a lookup target as the input variant. Its value field
defines the value type written by the input.
import {
datalist,
defineResource,
fields,
lookupVia,
} from '@backlit/sdk'
import { customerPicker, customers } from './customers.ts'
const orders = defineResource('orders', [
fields.ref('customer', () => customers, {
label: 'Customer',
display: 'name',
inputVariant: lookupVia(customerPicker, {
value: 'id',
label: 'name',
}),
}),
])
orders.view('detail', () =>
datalist({
customer: { id: 42, name: 'A. Customer' },
}).setFields(orders.pick('customer'))
)
export default ordersimport { defineResource, fields } from '@backlit/sdk'
export const customers = defineResource('customers', [
fields.number('id'),
fields.text('name'),
])
export const customerPicker = customers.lookup(
'picker',
(_ctx, lookup) =>
lookup
.setFields(customers.pick('id', 'name'))
.withData([])
){
"kind": "success",
"status": 200,
"node": {
"kind": "view",
"resource": "orders",
"name": "detail",
"slots": {
"content": [
{
"kind": "datalist",
"fields": [
{
"kind": "ref",
"name": "customer",
"label": "Customer",
"display": {
"kind": "text",
"name": "name",
"label": ""
},
"inputVariant": {
"kind": "search",
"lookup": {
"kind": "lookup",
"resource": "customers",
"name": "picker"
},
"value": "id",
"label": "name"
}
}
],
"data": {
"customer": "A. Customer"
}
}
]
}
}
}Cardinality
Use one for one related record and many for an array of related records.
import {
datalist,
defineResource,
fields,
} from '@backlit/sdk'
import { tags } from './tags.ts'
const products = defineResource('products', [
fields.ref('primaryTag', () => tags, {
label: 'Primary tag',
display: 'name',
cardinality: 'one',
}),
fields.ref('tags', () => tags, {
label: 'Tags',
display: 'name',
cardinality: 'many',
}),
])
products.view('detail', () =>
datalist({
primaryTag: { name: 'Lighting' },
tags: [{ name: 'Lighting' }, { name: 'Home' }],
}).setFields(products.pick('primaryTag', 'tags'))
)
export default productsimport { defineResource, fields } from '@backlit/sdk'
export const tags = defineResource('tags', [
fields.text('name'),
]){
"kind": "success",
"status": 200,
"node": {
"kind": "view",
"resource": "products",
"name": "detail",
"slots": {
"content": [
{
"kind": "datalist",
"fields": [
{
"kind": "ref",
"name": "primaryTag",
"cardinality": "one",
"label": "Primary tag",
"display": {
"kind": "text",
"name": "name",
"label": ""
}
},
{
"kind": "ref",
"name": "tags",
"cardinality": "many",
"label": "Tags",
"display": {
"kind": "text",
"name": "name",
"label": ""
}
}
],
"data": {
"primaryTag": "Lighting",
"tags": [
"Lighting",
"Home"
]
}
}
]
}
}
}Clone
Use configure when one view must change a role variant without changing the
shared field.
import {
datalist,
defineResource,
fields,
linkTo,
} from '@backlit/sdk'
import { categories, categoryDetail } from './categories.ts'
const category = fields.ref('category', () => categories, {
label: 'Category',
display: 'name',
})
const products = defineResource('products', [
category.configure({
display: fields.text('name').configure({
link: linkTo(
() => categoryDetail,
(record: { id: number }) => [record.id]
),
}),
}),
])
products.view('detail', () =>
datalist({
category: { id: 7, name: 'Lighting' },
}).setFields(products.pick('category'))
)
export default productsimport { defineResource, fields } from '@backlit/sdk'
export const categories = defineResource('categories', [
fields.number('id'),
fields.text('name'),
])
export const categoryDetail = categories.view(
'detail',
['id'],
() => []
){
"kind": "success",
"status": 200,
"node": {
"kind": "view",
"resource": "products",
"name": "detail",
"slots": {
"content": [
{
"kind": "datalist",
"fields": [
{
"kind": "ref",
"name": "category",
"label": "Category",
"display": {
"kind": "text",
"name": "name",
"label": "",
"link": {
"kind": "link",
"resource": "categories",
"view": "detail"
}
}
}
],
"data": {
"category": {
"value": "Lighting",
"args": [
7
]
}
}
}
]
}
}
}All options
A Ref field can use display and input targets, metadata, and many cardinality together.
import {
datalist,
defineResource,
fields,
linkTo,
lookupVia,
} from '@backlit/sdk'
import {
customerDetail,
customerPicker,
customers,
} from './customers.ts'
const orders = defineResource('orders', [
fields.ref('customers', () => customers, {
display: fields.text('name').configure({
link: linkTo(
() => customerDetail,
(record: { id: number }) => [record.id]
),
}),
label: 'Customers',
description: 'The customers connected to this order.',
inputVariant: lookupVia(customerPicker, {
value: 'id',
label: 'name',
}),
cardinality: 'many',
}),
])
orders.view('detail', () =>
datalist({
customers: [
{ id: 42, name: 'A. Customer' },
{ id: 43, name: 'B. Customer' },
],
}).setFields(orders.pick('customers'))
)
export default ordersimport { defineResource, fields } from '@backlit/sdk'
export const customers = defineResource('customers', [
fields.number('id'),
fields.text('name'),
])
export const customerDetail = customers.view(
'detail',
['id'],
() => []
)
export const customerPicker = customers.lookup(
'picker',
(_ctx, lookup) =>
lookup
.setFields(customers.pick('id', 'name'))
.withData([])
){
"kind": "success",
"status": 200,
"node": {
"kind": "view",
"resource": "orders",
"name": "detail",
"slots": {
"content": [
{
"kind": "datalist",
"fields": [
{
"kind": "ref",
"name": "customers",
"description": "The customers connected to this order.",
"cardinality": "many",
"label": "Customers",
"display": {
"kind": "text",
"name": "name",
"label": "",
"link": {
"kind": "link",
"resource": "customers",
"view": "detail"
}
},
"inputVariant": {
"kind": "search",
"lookup": {
"kind": "lookup",
"resource": "customers",
"name": "picker"
},
"value": "id",
"label": "name"
}
}
],
"data": {
"customers": [
{
"value": "A. Customer",
"args": [
42
]
},
{
"value": "B. Customer",
"args": [
43
]
}
]
}
}
]
}
}
}