← Back to Examples

🔎 External Search (FlexSearch)

Externalize the whole search with a searchCallback — the library stays lean

🌐 client — runs in the browser (element JS API) 🖥️ server — LiveView round-trip

ES01 · Fuzzy & Accent-Insensitive (flat list)

Set el.searchCallback (JS) to delegate the entire search to your own engine — here, a FlexSearch index.

The built-in search is a lean case-insensitive substring match. When you need fuzzy / partial / accent-insensitive / ranked matching, don't bloat the component — externalize the whole search via searchCallback and back it with your own index. Here that's FlexSearch (the same indexer @keenmate/web-treeview uses), loaded client-side. It is never part of the keen_web_multiselect bundle. From LiveView you can also handle search server-side via the hook's search event — this page shows the client-side route.

// FlexSearch lives entirely in your app — never in the multiselect bundle.
import FlexSearch from "https://esm.sh/flexsearch@0.8.212";

// Fold diacritics so accented labels match plain ASCII (ü→u, é→e), applied to
// both the indexed text and the query so they meet on the same normalized form.
const fold = (s) => String(s || "").normalize("NFD").replace(/\p{Diacritic}/gu, "").toLowerCase();

// The wrapper feeds options via the `data-options` attribute, which upstream parses
// into `optionsSource` — read that when the JS `options` property is empty.
const opts = (Array.isArray(el.options) && el.options.length)
  ? el.options
  : JSON.parse(el.optionsSource || "[]");

const index = new FlexSearch.Index({ tokenize: "full" }); // "full" = substring matching
opts.forEach((o, i) => index.add(i, fold(`${o.label} ${o.value} ${o.full_title}`)));

el.searchCallback = (term) =>
  (index.search(fold(term), { limit: 80 }) || []).map((i) => opts[i]);

The demo below is a flat list of cities with accented names. FlexSearch Charset.Normalize folds accents; tokenize: "full" matches partial tokens. Try zurich → Zürich, sao → São Paulo, krak → Kraków, munch → München. The built-in substring search would miss all of these.

ES02 · External Search on a Tree (full ISCO-08, 619 groups)

External search now composes with tree mode — matches keep their ancestors, and the index covers title + code + breadcrumb.

The whole ISCO-08 occupation tree, searched through FlexSearch. The component rebuilds the hierarchy from the returned matches, keeping each match's ancestors so indentation stays coherent. The index covers each occupation's title, ISCO code, and full breadcrumb — search 2211 non, welder, or health. Only unit groups (leaves) are selectable.

Source: International Standard Classification of Occupations, ISCO-08 (© International Labour Organization) — demo data.
🔌 Server round-trip
0
The LiveView server saw 0 event(s) from the wrapper.
(pick an option anywhere on this page)