Skip to content
Backlit
Esc
navigateopen⌘Jpreview
On this page

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 products
{
  "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"
          }
        }
      ]
    }
  }
}

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 products
{
  "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 products
{
  "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"
          }
        }
      ]
    }
  }
}

Configure the display field with link. The related record must contain every value that its field and link args callback use.

{
  "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 orders
{
  "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 products
{
  "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 products
{
  "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 orders
{
  "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
                ]
              }
            ]
          }
        }
      ]
    }
  }
}

Was this page helpful?