Skip to content
bahtuiv0.18.8

<baht-reference-picker>

Reference lookup: read-only input plus a magnifier that opens a typeahead. You supply fetcher(term); it owns debounce, dropdown and keyboard.

Lookup with a fetcher

Clearing emits baht-change with empty value and label. Set href to add an open-record link.

<baht-reference-picker label="Assigned to" placeholder="Search people"></baht-reference-picker>

<script>
  const el = document.querySelector('baht-reference-picker');
  const people = [
  { key: 'u1', label: 'Alice Tanaka' },
  { key: 'u2', label: 'Nok Srisuk' },
  { key: 'u3', label: 'Chai Boonmee' },
  ];
  el.fetcher = (term) =>
  Promise.resolve(people.filter((p) => p.label.toLowerCase().includes(term.toLowerCase())));
  el.addEventListener('baht-change', (e) => console.log(e.detail)); // { value, label }
</script>

In a form schema, type: 'reference' stores the picked record’s id. The JSON names a lookup; the functions live in the registry (they never travel in JSON):

{ "order": 2, "type": "reference", "key": "assignee", "label": "Assignee", "reference": "users", "required": true }
form.registry = {
references: {
users: {
// term + the form's current data (for dependent lookups: users of the picked team)
search: (term, data) => api.users({ q: term, team: data.team }), // [{ key, label, sub? }]
// id -> record, to show an existing value by name (and for the server check below)
resolve: (id) => api.user(id), // { key, label } | null
},
},
};

<baht-form> binds the lookup with the form data, shows an existing id by its resolved label (the raw id without resolve), and resolves labels in the read-only view too. On the server, validateSubmission checks the value is an id string; verifyReferences(schema, data, registry) from bank20baht-validator then resolves each id and reports the ones that do not exist.

Give the lookup list and columns, and the field becomes a box to type in, which suggests matches, with a search button that opens the records in <baht-reference-dialog>: a search on one column or on every column, a filter, sorting by a header and pages. Pressing a row’s first cell picks it.

Add walk, a ColumnMap, and the table’s Columns button offers those columns too, dot-walked ones included: the person adds, removes and reorders them, and the filter covers them. A dotted key reaches list as it is. savedColumns and saveColumns remember the choice, and savedFilters and saveFilters add Save Filters to the table.

registry.references.application = {
search: (term) => findApplications(term),
resolve: (id) => applicationById(id),
columns: [{ key: 'number', label: 'Application No.' }, { key: 'name', label: 'Application Name' }],
list: (query) => pageOfRows(allApplications, query), // or send the query to your API
};
NameTypeDefaultDescription
labelstring'Reference'Field label
valuestring''Selected record id
displaystring''Text shown for the value
placeholderstring''Input placeholder
invalidbooleanfalseError styling
hrefstring''Open-record link next to the lookup
lookup-labelstring'Look up records'Accessible name of the magnifier
debouncenumber | undefined200Milliseconds before a search
fetcherJS((term: string) => Promise<ReferenceOption[]>) | nullnullSearch function; options are { key, label, sub? }
lookupJSFieldReferenceLookup | nullnullField mode: { search(term), resolve?(id) } — <baht-form> binds registry.references[field.reference]
fieldJSFieldDescriptor—Field descriptor (type: 'reference') — switches to field mode; set by <baht-form>
disabledbooleanfalseDisabled
readonlybooleanfalse
requiredbooleanfalse
show-optionalbooleanfalseAppend the localized "(optional)" marker to the label when not required (set by <baht-form show-optional>).
errorJSstring | nullnull
EventdetailDescription
baht-change{ value, label }Standalone: a record picked or cleared
baht-input{ key, value }Field mode: the picked record id, or null when cleared
nameCustomEvent