{
  "id": "FI03",
  "title": "Toolbar filters",
  "topic": "filter",
  "use": "Two selects stand side by side in the toolbar. The first says which data set is on the screen and always has a value. The second is the filter and may stand on “all”. Both take effect at once — there is no Apply. A filter button comes in only when there is more behind it.",
  "decisions": [
    "The filter is a select, not a segmented control: a segmented control holds two or three short values; from four values on, a select. Beside the context select a segmented control reads as a view switch even with fewer, and two selects of the same build read as two dimensions of one purpose.",
    "The filter offers every state on its own: grouping states into Open and Finalized would make a record in error impossible to pick.",
    "The context select always has a value and the filter does not: the client stays set, while 'Status: all' is the empty filter — a record without a client does not exist, a list without a status filter does.",
    "Nothing opens: the filters are already there and only the rows change. A filter button appears only when more lies behind them.",
    "No label above the field: the toolbar is one line high, so the value carries the dimension ('Client: …', not the bare name).",
    "Both selects take effect at once; there is no Apply. The count stays under the toolbar, the active filter shows as a badge with a remove button, and the reset after it goes away with the last badge.",
    "The empty state names the filter as the cause and offers the reset in the same place; it does not reset the client, which is context."
  ],
  "try": [
    {
      "do": "Switch the client in the first select",
      "then": "the list swaps its data set, at once and without Apply"
    },
    {
      "do": "Choose a status in the second select",
      "then": "the list gets shorter, the count counts along, and the value stands as a badge under the toolbar"
    },
    {
      "do": "Choose Error",
      "then": "four documents are left — every status can be chosen on its own"
    },
    {
      "do": "Remove the badge with its cross",
      "then": "the filter is back on “Status: all”, without a detour through the field"
    },
    {
      "do": "Look for a filter button",
      "then": "there is none, because nothing lies behind these two"
    }
  ],
  "revision": 2,
  "changes": [
    {
      "revision": 2,
      "change": "A segmented control holds two or three short values and from four values on gives way to a select; beside the context select the filter is a select at any count."
    }
  ],
  "reviewed": true,
  "source": "<!-- Demo only, not part of the pattern. The table takes the height the screen leaves it; here it is set to fit the frame. -->\n\n<ed-data-grid id=\"fi03-documents\" label=\"Documents\" with-search>\n  <ed-button slot=\"toolbar-actions\">\n    <ed-icon slot=\"start\" name=\"plus\"></ed-icon>\n    Create document\n  </ed-button>\n  <ed-select id=\"fi03-client\" slot=\"toolbar-view\" aria-label=\"Client\" value=\"104688\" style=\"--ed-select-width: 14.5rem\">\n    <ed-option value=\"104721\">Client: Bergmann &amp; Söhne</ed-option>\n    <ed-option value=\"104688\">Client: Odenwälder</ed-option>\n    <ed-option value=\"104733\">Client: Steinbach-Wallner</ed-option>\n    <ed-option value=\"104802\">Client: Dr. Kettner-Lohmeyer</ed-option>\n    <ed-option value=\"104815\">Client: Pfeiffer-Zimmermann</ed-option>\n  </ed-select>\n  <ed-select id=\"fi03-status\" slot=\"toolbar-view\" aria-label=\"Status\" value=\"\" placeholder=\"Status: several\" style=\"--ed-select-width: 12.5rem\">\n    <ed-option value=\"\">Status: all</ed-option>\n    <ed-option value=\"Open\">Status: Open</ed-option>\n    <ed-option value=\"Reviewed\">Status: Reviewed</ed-option>\n    <ed-option value=\"Finalized\">Status: Finalized</ed-option>\n    <ed-option value=\"Error\">Status: Error</ed-option>\n  </ed-select>\n  <ed-empty-state slot=\"no-results\" icon=\"search\" size=\"medium\">\n    <span slot=\"label\">No document matches the active filter</span>\n    <span id=\"fi03-reason\"></span>\n    <ed-button id=\"fi03-reset\" slot=\"button\" appearance=\"outlined\">\n      <ed-icon slot=\"start\" name=\"close\"></ed-icon>\n      Reset filters\n    </ed-button>\n  </ed-empty-state>\n</ed-data-grid>\n\n<!-- Demo only, not part of the pattern. The product supplies documentsOf(client): the documents of one client, as { id, text, type, client, clerk, status }. -->\n\n<script type=\"module\">\n  const grid = document.getElementById('fi03-documents');\n  const client = document.getElementById('fi03-client');\n  const status = document.getElementById('fi03-status');\n  const reason = document.getElementById('fi03-reason');\n\n  const statusVariant = { Open: 'neutral', Reviewed: 'info', Finalized: 'success', Error: 'danger' };\n\n  grid.columns = [\n    { field: 'id', label: 'Document', width: 152, rowheader: true, pinned: 'left' },\n    { field: 'text', label: 'Posting text', minWidth: 224 },\n    { field: 'type', label: 'Document type', width: 176 },\n    { field: 'clerk', label: 'Processed by', width: 208 },\n    {\n      field: 'status',\n      label: 'Status',\n      width: 144,\n      pinned: 'right',\n      filterable: true,\n      filterType: 'set',\n      filterOptions: Object.keys(statusVariant).map(value => ({ value })),\n      formatter: value => {\n        const badge = document.createElement('ed-badge');\n        badge.setAttribute('variant', statusVariant[value]);\n        badge.textContent = value;\n        return badge;\n      }\n    }\n  ];\n  // The attribute, not `value`: the select may not be defined yet when this runs.\n  grid.data = documentsOf(client.getAttribute('value'));\n\n  // The empty state names what narrows the list, so it is not read as \"there is no data\".\n  function describe() {\n    const values = grid.filters.find(filter => filter.id === 'status')?.value ?? [];\n    const active = values.length ? [`Status — ${values.join(', ')}`] : [];\n    if (grid.searchTerm.trim()) active.push(`Search — ${grid.searchTerm.trim()}`);\n    reason.textContent = `Active: ${active.join(' · ')}`;\n  }\n\n  function setStatus(value) {\n    const others = grid.filters.filter(filter => filter.id !== 'status');\n    grid.filters = value ? [...others, { id: 'status', value: [value] }] : others;\n    describe();\n  }\n\n  client.addEventListener('change', () => {\n    grid.data = documentsOf(client.value);\n  });\n\n  status.addEventListener('change', () => setStatus(status.value));\n\n  // The status column has to be filterable for `grid.filters` to apply, so its menu filters too and\n  // can set several values; the select has no option for that and shows its placeholder instead.\n  grid.addEventListener('ed-data-grid-filter-change', event => {\n    const values = event.detail.filters.find(filter => filter.id === 'status')?.value ?? [];\n    status.value = values.length > 1 ? null : (values[0] ?? '');\n    describe();\n  });\n\n  document.getElementById('fi03-reset').addEventListener('click', () => {\n    grid.searchTerm = '';\n    status.value = '';\n    setStatus('');\n  });\n</script>",
  "page": "https://test-apps.eurodata.de/a/eurodata-ui/docs/patterns/filter/fi03-toolbar-filters/",
  "topicPage": "https://test-apps.eurodata.de/a/eurodata-ui/docs/patterns/filter/"
}
