# Find in grid

> A find bar on Ctrl/⌘+F that searches the cells' displayed text and steps through every match.

`findBar` turns on Ctrl/⌘+F inside the grid: a small bar opens over the top-right corner and finds text in the cells, as a browser finds text in a page, including rows that are scrolled out of view. Unlike a filter, it hides nothing.

Press the button, or click a cell and press Ctrl/⌘+F, then Enter to step through the matches.

Example: Find bar (find.svelte)

```svelte
<script lang="ts">
  import { Grid, type ColumnDef, type GridApi } from 'bo-grid';
  import { quotes } from './data';

  const columns: ColumnDef[] = [
    { type: 'text', key: 'symbol', header: 'Symbol', width: 100 },
    { type: 'text', key: 'name', header: 'Name', width: 160 },
    { type: 'text', key: 'sector', header: 'Sector', width: 130 },
    { type: 'price', key: 'price', header: 'Price' },
    { type: 'volume', key: 'volume', header: 'Volume', flex: 1 },
  ];
  let rows = $state(quotes());
  let api = $state<GridApi>();
</script>

<p style="margin: 0 0 10px">
  <button onclick={() => api?.openFind('Financials')}>Find “Financials”</button>
  <span style="opacity: 0.7">or click a cell and press Ctrl/⌘+F</span>
</p>
<Grid {rows} {columns} height={280} findBar onReady={(a) => (api = a)} />
```

data.ts:

```ts
// Small, fixed data for the docs' examples: every example reads the same
// symbols, so a reader compares features, not datasets.
// A type, not an interface: it then fits GridRow's index signature.
export type Quote = {
  id: number;
  symbol: string;
  name: string;
  sector: string;
  price: number;
  change: number;
  volume: number;
};

const BASE: Omit<Quote, 'id'>[] = [
  { symbol: 'VNM', name: 'Vinamilk', sector: 'Consumer', price: 68.5, change: 1.2, volume: 1_204_000 },
  { symbol: 'FPT', name: 'FPT Corp', sector: 'Technology', price: 132, change: -0.4, volume: 860_500 },
  { symbol: 'HPG', name: 'Hoa Phat', sector: 'Materials', price: 27.35, change: 0.74, volume: 3_412_900 },
  { symbol: 'VCB', name: 'Vietcombank', sector: 'Financials', price: 91.5, change: 0.55, volume: 1_986_200 },
  { symbol: 'MWG', name: 'Mobile World', sector: 'Consumer', price: 51.4, change: -1.1, volume: 2_250_400 },
  { symbol: 'SSI', name: 'SSI Securities', sector: 'Financials', price: 33.3, change: -0.45, volume: 4_104_700 },
  { symbol: 'VIC', name: 'Vingroup', sector: 'Real estate', price: 44.15, change: -0.11, volume: 1_530_100 },
  { symbol: 'GAS', name: 'PV Gas', sector: 'Energy', price: 71.8, change: 0.3, volume: 645_800 },
  { symbol: 'MSN', name: 'Masan', sector: 'Consumer', price: 76.2, change: 2.05, volume: 1_120_300 },
  { symbol: 'TCB', name: 'Techcombank', sector: 'Financials', price: 23.9, change: 0.84, volume: 5_870_000 },
  { symbol: 'VHM', name: 'Vinhomes', sector: 'Real estate', price: 41.6, change: -0.72, volume: 2_904_600 },
  { symbol: 'POW', name: 'PV Power', sector: 'Energy', price: 12.25, change: 1.66, volume: 6_315_200 },
];

/** A fresh copy of the quotes, so one example's edits never reach another. */
export function quotes(): Quote[] {
  return BASE.map((q, i) => ({ id: i + 1, ...q }));
}
```

## Turning it on

```svelte
<Grid {rows} {columns} height={480} findBar />
```

It is off by default, because while the grid has focus it takes Ctrl/⌘+F from the browser.

## How it searches

- It matches what the cells show (their formatted text), ignoring case, and counts the matches ("3 of 12").
- <kbd>Enter</kbd> and <kbd>Shift</kbd>+<kbd>Enter</kbd> step through them; each match is focused and scrolled into view.
- <kbd>Escape</kbd> closes the bar and returns focus to the grid.
- It searches in-memory rows (not a `source`), up to 10,000 matches.

Matches are found once per query and view, not on every tick, so on a live board the values can move after the bar has found them.

## Opening it from code

`api.openFind(query?)` opens the bar from your own button or shortcut, and searches for `query` at once when you give one:

```svelte
<script lang="ts">
  import { Grid, type GridApi } from 'bo-grid';
  let api = $state<GridApi>();
</script>

<button onclick={() => api?.openFind('Financials')}>Find</button>
<Grid {rows} {columns} height={480} findBar onReady={(a) => (api = a)} />
```

To narrow the rows instead of finding them, use the quick search in [Sorting & filtering](https://bonguynvan.github.io/bo-grid/docs/sorting-filtering/).

## Reference

- `findBar`: `boolean` (default `false`) — Ctrl/⌘+F in the grid opens a find bar: it matches the cells' displayed text (case-insensitive) and steps through matches with Enter / Shift+Enter, focusing and scrolling to each. Escape closes it. Off by default, as it takes Ctrl+F from the browser while the grid has focus. In-memory rows only.

- `openFind(query?: string): void` — Open the find bar (`findBar`), optionally searching for `query` at once.

  ```ts
  api.openFind('VNM');
  ```

---
Page: https://bonguynvan.github.io/bo-grid/docs/find/ · All pages: https://bonguynvan.github.io/bo-grid/llms.txt
