busy-office-ui
Menu

Pattern: value help

Who uses it: anyone typing a code they cannot remember — a buyer picking a material out of forty thousand, a clerk choosing a cost centre; dozens of times a day, inside a form they are part-way through. What "done" looks like: the right code is in the field, and the reader is back where they were with nothing else lost. The picker is a detour, not a destination — which is why choosing must put focus back in the field they were filling, not leave it at the top of the document. Not when the option set is small — a couple dozen fixed choices belong in a plain native select, not a dialog with search and paging behind it. This pattern is for the case a select cannot handle: a list too large to enumerate in one control.

Also called: search help or F4 help in SAP, a value list, a lookup, a picker. Same screen; this page is it (roadmap 132.2). Measured against what an F4 help characteristically offers: multi-criteria search is here already — the filter bar above the results takes as many criteria as the field needs, and the demo runs two; a configurable hit list needs nothing new either, because initTableToolbar() already ships column visibility and the results are an ordinary data table; a personal value list — the reader's recent or favourite picks — is a group of rows above the results, and the list itself is your data, not the framework's. None of the three is a second pattern.

The screen

Find a material

Materials matching your search
Material Description Group Plant
Hydraulic pump, 24V Pumps Warehouse A
Seal kit, 60 mm Seals Warehouse A
Filter cartridge, fine Filters Warehouse B
Hydraulic hose, 2 m Hoses Warehouse B
Pressure gauge, 400 bar Instruments Warehouse A
Seal kit, 80 mm Seals Warehouse C

Open it, type seal, and pick a row: the code lands in the field, the dialog closes, and focus returns to the control you left. Every part of this is a component that already ships — this pattern adds no CSS and no new component.

Anatomy

  1. The field and its trigger — a plain input beside a button carrying data-dialog-trigger. The field stays editable: someone who knows the code types it and never opens the picker.
  2. The picker — a dialog, modal because choosing is the only thing to do while it is open.
  3. Search & filters — filter bar at the top of the body, so narrowing happens where the eye already is.
  4. Results — a data table; the first cell is a button, not a link, because picking changes this form rather than navigating away.
  5. The filtered empty — state, and it says your filter excluded everything, which is a different message from "there is no master data".
  6. Result count and paging — pagination in the footer, where it does not compete with the results.

Data contract

The picker is a search endpoint, not a copy of the table. Forty thousand materials never reach the browser.

  • GET /materials?q=&group=&page= → one page of matches plus a total. The total drives both the count and whether paging appears at all.
  • Debounce the search server-side of the keystroke — one request per pause, not per character. The demo above filters in the browser only because six rows fit in the page.
  • Picking returns the whole record, not just the code: the form usually needs the description and unit too, and a second request to fetch what the picker already had is a wasted round trip.
  • A 4xx leaves the dialog open with the error in place of the results. Closing it would discard the reader's search.

States

StateWhat the screen shows
LoadingThe table keeps its header and shows data-loading; the filter bar stays usable so a slow query can be narrowed rather than waited out.
Empty — no data at all"No materials exist yet", with the action that creates one. This is a setup problem.
Empty — filtered outA different message: the data exists, the filter excluded it, and the action is clear filters. Showing the setup message here sends the reader to create a duplicate.
Too many resultsPage, and say the total. "Showing 1–20 of 4,318" tells the reader to narrow; a bare first page does not.
ErrorInside the dialog, results replaced, search preserved.
PermissionIf the reader may not browse master data, the trigger is absent — not disabled. A disabled button invites a support ticket.
No JSLike the command bar, the "Find…" trigger has no native popovertarget — initDialogs()'s click listener is the only thing that calls showModal(). With no JS the trigger is inert: the picker dialog never opens, so the field can only be filled by typing a value directly, and the in-dialog filtering script never runs.

Markup

<!-- the field, and the control that opens the picker -->
<div class="bo-form-field">
  <label class="bo-form-field__label" for="vh-material">Material</label>
  <div class="bo-cluster">
    <input class="bo-input bo-input--code" id="vh-material" value="MAT-4471" />
    <button class="bo-btn bo-btn--secondary" type="button"
            data-dialog-trigger="vh-dialog" aria-label="Find a material">Find…</button>
  </div>
</div>

<dialog class="bo-dialog bo-dialog--wide" id="vh-dialog" aria-labelledby="vh-title">
  <div class="bo-dialog__header">
    <h2 class="bo-dialog__title" id="vh-title">Find a material</h2>
    <form method="dialog"><button class="bo-btn bo-btn--sm bo-btn--ghost" type="submit">×</button></form>
  </div>
  <div class="bo-dialog__body">
    <form class="bo-filter-bar" role="search">…search + filters…</form>
    <table class="bo-data-table">…results…</table>
    <div class="bo-state" hidden>…the empty that means "your filter excluded everything"…</div>
  </div>
  <div class="bo-dialog__footer">
    <nav class="bo-pagination">…</nav>
  </div>
</dialog>

Components used

complexity 2 of 4

↑↓ move Enter open Esc close