Filters and interactions

Filters and selections let users change a report without giving the browser unrestricted query control. Dashboard YAML defines allowed fields, operators, option sources, URL state, semantic mappings, and targets; the server validates and applies each command.

This guide describes the currently accepted dashboard configuration. See Filter and slicer target architecture for the state, command, targeting, and option-domain design.

Define dashboard filters

Define a categorical filter

filters:
  state:
    label: State
    description: Limit results to one or more customer states.
    field: customer_state
    predicates:
      - kind: set
        operators: [in, not_in]
    options: {kind: distinct, limit: 50}
filter_bindings:
  state:
    filter: state
    default: {kind: unfiltered}
    selection: {mode: multiple, max_selected_values: 50}
    url: {param: state, encoding: typed_v1}
    pane: {visible: true, order: 10}

The definition owns semantic meaning and legal predicates. The binding owns state, scope, targets, selection limits, URL identity, editability, and Filters-pane presentation. Distinct options are loaded lazily in bounded pages. For thousands of identifiers, enable search and keep page sizes conservative.

Optionally present the same report binding as a page slicer:

- id: state-filter
  kind: slicer
  binding: {scope: report, id: state}
  presentation: {style: dropdown, search: true}
  placement: {col: 1, row: 1, col_span: 4, row_span: 2}

The pane card and slicer are separate shells around the same canonical binding state. Removing either presentation does not remove the binding or its filtering effect.

Define date and relative-period predicates

filters:
  purchase_date:
    label: Purchase date
    field: purchase_date
    predicates:
      - kind: range
      - kind: relative_period
filter_bindings:
  purchase_date:
    filter: purchase_date
    default: {kind: unfiltered}
    url: {param: period, encoding: typed_v1}
    pane: {visible: true, order: 20}

Date, timestamp, calendar, timezone, and week-start semantics come from the semantic field. A date derived from a UTC timestamp may differ from a local-business date near midnight; resolve that in the model instead of compensating in each presentation.

Define a text filter

Text definitions expose only their allowed operator set:

filters:
  category:
    label: Category
    field: category
    predicates:
      - kind: comparison
        operators: [contains, equals, starts_with, ends_with, not_contains]
filter_bindings:
  category:
    filter: category
    default: {kind: unfiltered}
    url: {param: category, encoding: typed_v1}
    pane: {visible: true, order: 30}

typed_v1 serializes the canonical typed expression as unpadded base64url. The server parses and normalizes it; the browser does not maintain a second predicate parser. Default and unfiltered values are omitted. Stable parameter names are compatibility-sensitive, so rename them intentionally.

Control interaction scope

Scope filter targets

By default, a binding applies to every semantically compatible consumer in its scope. Use targets: {include: [...]} or targets: {exclude: [...]} when it should affect only part of a page or report. Page targets are component IDs; report targets are qualified pageID/componentID identities. Include and exclude are mutually exclusive.

Test combinations, not just filters in isolation. Two individually valid filters can produce an empty intersection, and users should see a deliberate empty state rather than a broken chart.

Map visual or table selections

Selection interactions map delivered row values back to semantic fields:

interaction:
  row_selection:
    toggle: true
    mappings:
      - field: orders.order_id
        fact: orders
        value: order_id
        label: order_id
    targets:
      - revenue_kpi
      - revenue_by_month

value names a delivered result field. field and fact establish semantic identity. The server rejects incomplete or forged mappings before applying them. Targets are dashboard definition IDs, not arbitrary CSS selectors or browser element IDs.

Point selection on supported visuals uses the same principle. Keep mapping values typed: a numeric zero, boolean false, string "0", and null are not interchangeable.

Verify predictable interactions

  • Make selection state visually apparent.
  • Provide a clear way to toggle or clear it.
  • Target only components whose change users can anticipate.
  • Avoid cycles where several selections continually redefine one another.
  • Verify behavior when page filters and selections are both active.
  • Ensure a superseded interaction cannot restore an older result.

Start with standalone correct visuals, then add one interaction at a time. The generated Dashboard configuration lists current filter and interaction fields.