Links

Search

In Forest Admin, pages which show lists of records have a free-text search widget on top of them.
A search bar on the main list-view

Search modes

Two search modes are supported: normal and extended.
  • All searches start by being a "normal search".
  • If the result the user is looking for is not found, it is possible to trigger an extended search from the user interface.
Extended search call to action

Default behavior

When not defined otherwise by the data source, the search behavior is to attempt to search within columns of the collection (in normal mode), or columns of the collection of direct relations (in extended mode).
By default, Forest Admin will search only on some columns, depending on their respective types.
Column Type
Default search behavior
Enum
Column is equal to the search string (case-insensitive)
Number
Column is equal to the search string (if the search string is numeric)
String
Column contains the search string (case-insensitive)
Uuid
Column is equal to the search string
Other types
Column is ignored by the default search handler

Customization

You may want to change how the search bar behaves in your admin panel.
For instance:
  • Search only on the columns which are relevant to your use case.
  • Use full-text indexes of your data (i.e Postgres tsquery and tsvector, Algolia, Elastic search, ...)
To customize the search bar, you must define a handler that returns a ConditionTree.

Making the search case-sensitive by default

In this example, we use the searchExtended condition to toggle between case-sensitive and insensitive searches.
use ForestAdmin\AgentPHP\DatasourceCustomizer\CollectionCustomizer;
use ForestAdmin\AgentPHP\DatasourceToolkit\Components\Query\ConditionTree\Operators;
$forestAgent->customizeCollection(
'People',
function (CollectionCustomizer $builder) {
$builder->replaceSearch(
function ($searchString, $extendedMode) {
$operator = $extendedMode ? Operators::CONTAINS : Operators::ICONTAINS;
return [
'aggregator' => 'Or',
'conditions' => [
['field' => 'firstName', 'operator' => $operator, 'value' => $searchString],
['field' => 'lastName', 'operator' => $operator, 'value' => $searchString],
]
];
}
);
}
);

Changing searched columns

use ForestAdmin\AgentPHP\DatasourceCustomizer\CollectionCustomizer;
use ForestAdmin\AgentPHP\DatasourceToolkit\Components\Query\ConditionTree\Operators;
$forestAgent->customizeCollection(
'Product',
function (CollectionCustomizer $builder) {
$builder->replaceSearch(
function ($searchString, $extendedMode) {
$productReferenceRegexp = '/^[a-f]{16}$/i';
$barCodeRegexp = '/^[0-9]{10}$/i';
// User is searching using a product reference.
if (preg_match($productReferenceRegexp, $str)) {
return ['field' => 'reference', 'operator' => Operators::EQUAL, 'value' => $searchString];
}
// User is search a bar-code
if (preg_match($barCodeRegexp, $str)) {
return ['field' => 'barCode', 'operator' => Operators::EQUAL, 'value' => $searchString];
}
// User is searching something else, in "normal mode", let's only search in the product name
if (! $extendedMode) {
return ['field' => 'name', 'operator' => Operators::CONTAINS, 'value' => $searchString];
}
// In extended mode, we search on name, description and brand name
return [
'aggregator' => 'Or',
'conditions' => [
['field' => 'name', 'operator' => Operators::CONTAINS, 'value' => $searchString],
['field' => 'description', 'operator' => Operators::CONTAINS, 'value' => $searchString],
['field' => 'brand:name', 'operator' => Operators::EQUAL, 'value' => $searchString],
]
];
}
);
}
);

Calling an external API

If your data is indexed using a SaaS, external store, or full-text index, you can call it in the search handler.
use ForestAdmin\AgentPHP\DatasourceCustomizer\CollectionCustomizer;
use ForestAdmin\AgentPHP\DatasourceToolkit\Components\Query\ConditionTree\Operators;
use Algolia\AlgoliaSearch\SearchClient;
$forestAgent->customizeCollection(
'Product',
function (CollectionCustomizer $builder) {
$builder->replaceSearch(
function ($searchString, $extendedMode) {
$client = SearchClient::create("YourApplicationID", "YourWriteAPIKey");
$index = $client->initIndex("test_index");
$results = $index->search(
$searchString,
[
'attributesToRetrieve' => ['id'],
'hitsPerPage' => 50,
]
);
return ['field' => 'id', 'operator' => Operators::IN, 'value' => array_map(fn ($hit) => $hit['id'], $results)];
}
);
}
);