docs/content/guides/navigation/searching-values/searching-values.md
Enable the Search plugin and call query() on each keystroke to highlight matching cells across the grid.
[[toc]]
::: only-for react
::: tip
To use the Handsontable API, you'll need access to the Handsontable instance. You can do that by utilizing a reference to the HotTable component, and reading its hotInstance property.
For more information, see the Instance methods page.
:::
:::
::: only-for angular
::: tip
To use the Handsontable API, you'll need access to the Handsontable instance. You can do that by utilizing a reference to the HotTable component, and reading its hotInstance property.
For more information, see the Instance access page.
:::
:::
The Search plugin lets you scan all cells in the grid and get back a list of matches. Enable it by setting the search option to true or to a configuration object.
Once enabled, the plugin exposes the query(queryStr) method. Call it with a search string whenever the user types. By default, the search is case-insensitive and matches partial cell values.
The example below:
Search plugin by setting search to truekeyup events on a search inputquery() on each keystroke and re-renders the grid to apply highlighting::: only-for javascript
::: example #example1 --html 1 --js 2 --ts 3
:::
:::
::: only-for react
::: example #example1 :react --js 1 --ts 2
:::
:::
::: only-for angular
::: example #example1 :angular --ts 1 --html 2
:::
:::
You can style search results with a custom CSS class, using the Search plugin's searchResultClass option.
::: tip
Always scope your custom class under the theme and .handsontable selectors (for example, .ht-theme-main .handsontable .my-class) to avoid conflicts with other styles. For more details, see the Themes guide.
:::
The example below highlights search results with a pink background and red text. To do this, it:
my-class, scoped to .ht-theme-main .handsontableSearch plugin with a configuration objectsearchResultClass to 'my-class'::: only-for javascript
::: example #example2 --css 1 --html 2 --js 3 --ts 4
:::
:::
::: only-for react
::: example #example2 :react --css 1 --js 2 --ts 3
:::
:::
::: only-for angular
::: example #example2 :angular --ts 1 --html 2
:::
:::
You can replace the built-in substring search with a custom query method, using the queryMethod option.
The example below searches only for exact matches. To do this, it:
onlyExactMatch that uses strict equality (===)Search plugin with a configuration objectqueryMethod to onlyExactMatch::: only-for javascript
::: example #example3 --html 1 --js 2 --ts 3
:::
:::
::: only-for react
::: example #example3 :react --js 1 --ts 2
:::
:::
::: only-for angular
::: example #example3 :angular --ts 1 --html 2
:::
:::
You can add a custom callback function, using the Search plugin's callback option.
The example below displays the number of matching search results. To do this, it:
searchResultCounter that counts matches and calls the default callback to preserve highlightingSearch plugin with a configuration objectcallback to searchResultCounter::: only-for javascript
::: example #example4 --html 1 --js 2 --ts 3
:::
:::
::: only-for react
::: example #example4 :react --js 1 --ts 2
:::
:::
::: only-for angular
::: example #example4 :angular --ts 1 --html 2
:::
:::
After following these steps, typing in your search input highlights matching cells with the htSearchResult CSS class. The query() call returns an array of matching { row, col, data } objects that you can use to build a results counter or navigate between matches.
query() worksCalling query(queryStr, [callback], [queryMethod]) does two things:
queryMethod.callback to update cell metadata (isSearchResult).It returns an array of result objects - one for each matching cell:
| Property | Type | Description |
|---|---|---|
row | number | Visual row index of the matching cell |
col | number | Visual column index of the matching cell |
data | string|number|null | Value of the matching cell |
After calling query(), call hot.render() to refresh visual highlighting.
After query() runs, every cell where isSearchResult === true automatically receives the CSS class htSearchResult. You can replace this class in two ways:
search: { searchResultClass: 'my-class' }hot.getPlugin('search').setSearchResultClass('my-class')queryMethod signatureThe queryMethod function determines whether the query string matches a cell value. It is called once per cell during every query() call.
function queryMethod(query, value, cellProperties) {
// return true for a match, false otherwise
}
| Parameter | Type | Description |
|---|---|---|
query | string | The search string passed to query() |
value | string|number|null | The cell value (from getDataAtCell()) |
cellProperties | object | The cell's metadata object (includes locale, type, and other cell options) |
The built-in default performs a case-insensitive, locale-aware substring match:
function defaultQueryMethod(query, value, cellProperties) {
if (query === undefined || query === null || query.length === 0) {
return false;
}
if (value === undefined || value === null) {
return false;
}
return value.toString().toLocaleLowerCase(cellProperties.locale)
.indexOf(query.toLocaleLowerCase(cellProperties.locale)) !== -1;
}
You can set a custom query method in three ways:
search: { queryMethod: myQueryMethod }hot.getPlugin('search').setQueryMethod(myQueryMethod)query() call: searchPlugin.query(queryStr, callback, myQueryMethod) (applies to that call only)callback signatureThe callback function is called for every cell during a query() run, whether or not the cell matches. It is responsible for updating cell metadata so the renderer knows which cells to highlight.
function callback(instance, row, col, data, testResult) {
// update cell metadata based on testResult
}
| Parameter | Type | Description |
|---|---|---|
instance | Handsontable | The Handsontable instance |
row | number | Visual row index |
col | number | Visual column index |
data | string|number|null | The cell value |
testResult | boolean | true if the cell matches the query, false otherwise |
The built-in default sets the isSearchResult flag on each cell's metadata:
function defaultCallback(instance, row, col, data, testResult) {
instance.getCellMeta(row, col).isSearchResult = testResult;
}
If you override the callback to add custom logic (for example, to count results), call the default behavior manually so that cell highlighting still works.
You can set a custom callback in three ways:
search: { callback: myCallback }hot.getPlugin('search').setCallback(myCallback)query() call: searchPlugin.query(queryStr, myCallback) (applies to that call only)queryMethod and callbackBoth queryMethod and callback can be overridden for individual cells, columns, or rows using Handsontable's cascading configuration model. Set a search object directly in a cell, columns, or rows entry:
handsontable({
data: myData,
search: true,
columns: [
{},
// Column 1: exact match only, everything else uses the global queryMethod
{
search: {
queryMethod(queryStr, value) {
return queryStr.toString() === value.toString();
}
}
}
]
});
You can also set it programmatically on a specific cell using setCellMeta():
hot.setCellMeta(row, col, 'search', {
queryMethod(queryStr, value) {
return queryStr.toString() === value.toString();
}
});
Per-cell settings take precedence over the plugin-level queryMethod and callback. Only queryMethod and callback support per-cell overrides - searchResultClass does not.
Configuration options
<div class="boxes-list"> </div>Plugins
<div class="boxes-list"> </div>