Skip to content

Drill-Down

Summary

A drill-down field is a read-only field with a lookup.endpoint that lets the user navigate to related data. This page covers how to define drill-down fields and implement the endpoint.

Defining a drill-down field

A drill-down field uses three standard field properties — no special type needed:

json
{
  "id": "balance_lcy",
  "label": "Balance (LCY)",
  "type": "Decimal",
  "value": "45,000.00",
  "editable": false,
  "color": "yellow",
  "bold": true,
  "lookup": {
    "endpoint": "/drilldown/balance_lcy/10000"
  }
}

The client blocks editing and makes Ctrl+Enter fetch the lookup.endpoint. color and bold are optional — omit them if you don't need the yellow/bold convention.

The drill-down endpoint

Route

The URL is whatever you bake into lookup.endpoint. A common pattern:

GET /drilldown/{field_id}/{key} → ScreenContract

Your server decides what to show

The server controls the URL structure and knows what key to embed:

/drilldown/balance_lcy/10000
  → show ledger entries for customer 10000

/drilldown/customer_no/10000
  → show the customer card for customer 10000

/drilldown/document_no/INV-1001
  → show the invoice card

Response

Return a standard ScreenContract — any layout works:

  • List — most common. "Balance" → show ledger entries as a list.
  • Card — "Customer No." → show the customer card.
  • HeaderLines — "Document No." → show the full document with lines.

The client pushes it onto the screen stack. Esc pops back.

Example: ledger entries drill-down

json
{
  "layout": "List",
  "title": "Customer Ledger Entries - 10000",
  "lines": {
    "columns": [
      {
        "id": "posting_date",
        "label": "Posting Date",
        "type": "Date",
        "width": 12
      },
      {
        "id": "document_no",
        "label": "Document No.",
        "type": "Text",
        "width": 15
      },
      {
        "id": "description",
        "label": "Description",
        "type": "Text",
        "width": "fill"
      },
      {
        "id": "amount",
        "label": "Amount",
        "type": "Decimal",
        "width": 14,
        "align": "right"
      }
    ],
    "rows": [
      {
        "index": 0,
        "values": [
          "10-03-26",
          "INV-1001",
          "Order payment",
          "20,000.00"
        ]
      },
      {
        "index": 1,
        "values": [
          "15-03-26",
          "INV-1005",
          "Service invoice",
          "25,000.00"
        ]
      }
    ],
    "selectable": true,
    "on_select": "/screen/ledger_entry_card/{0}"
  }
}

Multi-level drill-down

Drill-down screens can contain their own drill-down fields, creating a navigation chain:

Customer Card (Balance: 45,000)
  └── Ctrl+Enter on Balance → Ledger Entries List
        └── Enter → Ledger Entry Card
              ├── Ctrl+Enter on Customer No. → Customer Card
              └── Ctrl+Enter on Document No. → Invoice Card

Each level is a standard screen on the stack. The user can drill down multiple levels and Esc back through the entire chain.

To make this work, put drill-down fields on your screens:

json
{
  "id": "customer_no",
  "label": "Customer No.",
  "type": "Text",
  "value": "10000",
  "editable": false,
  "color": "yellow",
  "bold": true,
  "lookup": {
    "endpoint": "/drilldown/customer_no/10000"
  }
}

Computed values after save

When the user saves a card, computed values may change (e.g., the balance changes after a ledger entry is modified). Your save response should return a fresh ScreenContract with recalculated values.

Drill-down vs Lookup

These are different use cases that share the same lookup mechanism:

Drill-downLookup
PurposeView source data (read-only)Select a valid value
FieldNon-editable with lookupEditable with lookup
Returns a valueNo (browse only)Yes (writes to field)
AutofillNoYes

The client determines the behavior from editable and lookup — the user does not need to know this distinction.