Filters on grids act as predefined search options for each grid. Having a grid of objects you can filter out only those with a specified name, or value etc. Here you can find the supported filters. Keep in mind you can very easily define your own ones!
String
Simplest filter type. It can filter by one or multiple fields.
Filter by one field
src/Grid/UserGrid.php
<?phpdeclare(strict_types=1);namespaceApp\Grid;use App\Entity\User;use Sylius\Bundle\GridBundle\Builder\Filter\Filter;use Sylius\Bundle\GridBundle\Builder\Filter\StringFilter;use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;use Sylius\Bundle\GridBundle\Grid\AbstractGrid;use Sylius\Component\Grid\Attribute\AsGrid;#[AsGrid(resourceClass:User::class,name:'app_user',)]finalclassUserGridextendsAbstractGrid{publicfunction__invoke(GridBuilderInterface $gridBuilder):void{$gridBuilder->withFilters(Filter::create('username','string'),Filter::create('email','string'),Filter::create('firstName','string'),Filter::create('lastName','string'),) // can be simplified using StringFilter->withFilters(StringFilter::create('username'),StringFilter::create('email'),StringFilter::create('firstName'),StringFilter::create('lastName'),);}}
Filter by multiple fields
Search options
This filter allows the user to select the following search options:
contains
not contains
equal
not equal
starts with
ends with
empty
not empty
in
not in
member of
If you don't want to display all these matching possibilities, you can choose just one of them. Then only the input field will be displayed. You can achieve it like this:
By configuring the filter as shown above, you will create an input field that filters user objects based on whether their username contains a given string.
Boolean
This filter checks if a value is true or false.
Date
This filter checks if a chosen datetime field is between given dates.
Entity
This type filters by a chosen entity.
Money
This filter checks if an amount is within the specified range and is in the selected currency
Warning
Providing different scale values between form_options and options may cause unwanted, and plausibly volatile results.
Exists
This filter checks if the specified field contains any value
Select
This type filters by a value chosen from the defined list
Creating a custom Filter
Sylius Grids come with built-in filters, but there are use-cases where you need something more than a basic filter. Grids let you define your own filter types!
To add a new filter, we need to create an appropriate class and form type.
And the form type:
And the form type:
Create a template for the filter, similar to the existing ones:
If you use autoconfiguration, the filter is automatically registered as a grid filter.
But if you don't use autoconfiguration, let's register your new filter type as a service.
Now you can use your new filter type in any grid configuration!
<?php
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\Filter\StringFilter;
use Sylius\Bundle\GridBundle\Builder\GridBuilder;
use Sylius\Bundle\GridBundle\Config\GridConfig;
return static function (GridConfig $grid): void {
$grid->addGrid(GridBuilder::create('app_user', '%app.model.user.class%')
->withFilters(
Filter::create('username', 'string'),
Filter::create('email', 'string'),
Filter::create('firstName', 'string'),
Filter::create('lastName', 'string'),
)
// can be simplified using StringFilter
->withFilters(
StringFilter::create('username'),
StringFilter::create('email'),
StringFilter::create('firstName'),
StringFilter::create('lastName'),
)
)
};
src/Grid/UserGrid.php
<?php
declare(strict_types=1);
namespace App\Grid;
use App\Entity\User;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\Filter\StringFilter;
use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;
use Sylius\Bundle\GridBundle\Grid\AbstractGrid;
use Sylius\Component\Grid\Attribute\AsGrid;
#[AsGrid(
resourceClass: User::class,
name: 'app_user',
)]
final class UserGrid extends AbstractGrid
{
public function __invoke(GridBuilderInterface $gridBuilder): void
{
$gridBuilder
->withFilters(
Filter::create('username', 'string')
->setOptions(['fields' => ['username', 'email', 'firstName', 'lastName']])
)
// can be simplified using StringFilter
->withFilters(
StringFilter::create('username', ['username', 'email', 'firstName', 'lastName'])
)
;
}
}
<?php
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\Filter\StringFilter;
use Sylius\Bundle\GridBundle\Builder\GridBuilder;
use Sylius\Bundle\GridBundle\Config\GridConfig;
return static function (GridConfig $grid): void {
$grid->addGrid(GridBuilder::create('app_user', '%app.model.user.class%')
->withFilters(
Filter::create('username', 'string')
->setOptions(['fields' => ['username', 'email', 'firstName', 'lastName']])
)
// can be simplified using StringFilter
->withFilters(
StringFilter::create('username', ['username', 'email', 'firstName', 'lastName'])
)
)
};
src/Grid/UserGrid.php
<?php
declare(strict_types=1);
namespace App\Grid;
use App\Entity\User;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\Filter\StringFilter;
use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;
use Sylius\Bundle\GridBundle\Grid\AbstractGrid;
use Sylius\Component\Grid\Attribute\AsGrid;
#[AsGrid(
resourceClass: User::class,
name: 'app_user',
)]
final class UserGrid extends AbstractGrid
{
public function __invoke(GridBuilderInterface $gridBuilder): void
{
$gridBuilder
->withFilters(
Filter::create('username', 'string')
->setFormOptions([
'type' => 'contains',
])
)
// can be simplified using StringFilter
->withFilters(
StringFilter::create('username', null, 'contains')
)
;
}
}
<?php
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\Filter\StringFilter;
use Sylius\Bundle\GridBundle\Builder\GridBuilder;
use Sylius\Bundle\GridBundle\Config\GridConfig;
return static function (GridConfig $grid): void {
$grid->addGrid(GridBuilder::create('app_user', '%app.model.user.class%')
->withFilters(
Filter::create('username', 'string')
->setFormOptions([
'type' => 'contains',
])
)
// can be simplified using StringFilter
->withFilters(
StringFilter::create('username', null, 'contains')
)
)
};
src/Grid/UserGrid.php
<?php
declare(strict_types=1);
namespace App\Grid;
use App\Entity\User;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\Filter\BooleanFilter;
use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;
use Sylius\Bundle\GridBundle\Grid\AbstractGrid;
use Sylius\Component\Grid\Attribute\AsGrid;
#[AsGrid(
resourceClass: User::class,
name: 'app_user',
)]
final class UserGrid extends AbstractGrid
{
public function __invoke(GridBuilderInterface $gridBuilder): void
{
$gridBuilder
->withFilters(
Filter::create('enabled', 'boolean')
)
// can be simplified using BooleanFilter
->withFilters(
BooleanFilter::create('enabled')
)
;
}
}
<?php
use Sylius\Bundle\GridBundle\Builder\Filter\BooleanFilter;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\GridBuilder;
use Sylius\Bundle\GridBundle\Config\GridConfig;
return static function (GridConfig $grid): void {
$grid->addGrid(GridBuilder::create('app_user', '%app.model.user.class%')
->withFilters(
Filter::create('enabled', 'boolean')
)
// can be simplified using BooleanFilter
->withFilters(
BooleanFilter::create('enabled')
)
)
};
src/Grid/UserGrid.php
<?php
declare(strict_types=1);
namespace App\Grid;
use App\Entity\User;
use Sylius\Bundle\GridBundle\Builder\Filter\DateFilter;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;
use Sylius\Bundle\GridBundle\Grid\AbstractGrid;
use Sylius\Component\Grid\Attribute\AsGrid;
#[AsGrid(
resourceClass: User::class,
name: 'app_user',
)]
final class UserGrid extends AbstractGrid
{
public function __invoke(GridBuilderInterface $gridBuilder): void
{
$gridBuilder
->withFilters(
Filter::create('createdAt', 'date'),
Filter::create('completedAt', 'date'),
)
// can be simplified using DateFilter
->withFilters(
DateFilter::create('createdAt'),
DateFilter::create('completedAt'),
)
;
}
}
config/packages/sylius_grid.yaml
sylius_grid:
grids:
app_order:
filters:
createdAt:
type: date
completedAt:
type: date
config/packages/sylius_grid.php
<?php
use Sylius\Bundle\GridBundle\Builder\Filter\DateFilter;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\GridBuilder;
use Sylius\Bundle\GridBundle\Config\GridConfig;
return static function (GridConfig $grid): void {
$grid->addGrid(GridBuilder::create('app_user', '%app.model.user.class%')
->withFilters(
Filter::create('createdAt', 'date'),
Filter::create('completedAt', 'date'),
)
// can be simplified using DateFilter
->withFilters(
DateFilter::create('createdAt'),
DateFilter::create('completedAt'),
)
)
};
src/Grid/UserGrid.php
<?php
declare(strict_types=1);
namespace App\Grid;
use App\Entity\User;
use Sylius\Bundle\GridBundle\Builder\Filter\EntityFilter;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;
use Sylius\Bundle\GridBundle\Grid\AbstractGrid;
use Sylius\Component\Grid\Attribute\AsGrid;
#[AsGrid(
resourceClass: User::class,
name: 'app_user',
)]
final class UserGrid extends AbstractGrid
{
public function __invoke(GridBuilderInterface $gridBuilder): void
{
$gridBuilder
->withFilters(
Filter::create('channel', 'entity')
->setFormOptions(['class' => '%app.model.channel.class%']),
Filter::create('customer', 'entity')
->setFormOptions(['class' => '%app.model.customer.class%']),
)
// can be simplified using EntityFilter
->withFilters(
EntityFilter::create('channel', '%app.model.channel.class%'),
EntityFilter::create('customer', '%app.model.customer.class%'),
)
;
}
}
config/packages/sylius_grid.yaml
sylius_grid:
grids:
app_order:
filters:
channel:
type: entity
form_options:
class: "%app.model.channel.class%"
# You can pass any form options available in Entity Type
# See https://symfony.com/doc/current/reference/forms/types/entity.html
multiple: true
customer:
type: entity
form_options:
class: "%app.model.customer.class%"
config/packages/sylius_grid.php
<?php
use Sylius\Bundle\GridBundle\Builder\Filter\EntityFilter;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\GridBuilder;
use Sylius\Bundle\GridBundle\Config\GridConfig;
return static function (GridConfig $grid): void {
$grid->addGrid(GridBuilder::create('app_user', '%app.model.user.class%')
->withFilters(
Filter::create('channel', 'entity')
->setFormOptions([
'class' => '%app.model.channel.class%'
// You can pass any form options available in Entity Type
// See https://symfony.com/doc/current/reference/forms/types/entity.html
'multiple' => true,
]),
Filter::create('customer', 'entity')
->setFormOptions(['class' => '%app.model.customer.class%']),
)
// can be simplified using EntityFilter
->withFilters(
EntityFilter::create('channel', '%app.model.channel.class%')
->addFormOption('multiple', true),
EntityFilter::create('customer', '%app.model.customer.class%'),
)
)
};
src/Grid/UserGrid.php
<?php
declare(strict_types=1);
namespace App\Grid;
use App\Entity\User;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\Filter\MoneyFilter;
use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;
use Sylius\Bundle\GridBundle\Grid\AbstractGrid;
use Sylius\Component\Grid\Attribute\AsGrid;
#[AsGrid(
resourceClass: User::class,
name: 'app_user',
)]
final class UserGrid extends AbstractGrid
{
public function __invoke(GridBuilderInterface $gridBuilder): void
{
$gridBuilder
->withFilters(
Filter::create('total', 'money')
->setFormOptions(['scale' => 3])
->setOptions([
'currency_field' => 'currencyCode',
'scale' => 3,
])
)
// can be simplified using MoneyFilter
->withFilters(
MoneyFilter::create('total', 'currencyCode', 3)
)
;
}
}
<?php
use Sylius\Bundle\GridBundle\Builder\Filter\MoneyFilter;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\GridBuilder;
use Sylius\Bundle\GridBundle\Config\GridConfig;
return static function (GridConfig $grid): void {
$grid->addGrid(GridBuilder::create('app_user', '%app.model.user.class%')
->withFilters(
Filter::create('total', 'money')
->setFormOptions(['scale' => 3])
->setOptions([
'currency_field' => 'currencyCode',
'scale' => 3,
])
)
// can be simplified using MoneyFilter
->withFilters(
MoneyFilter::create('total', 'currencyCode', 3)
)
)
};
src/Grid/UserGrid.php
<?php
declare(strict_types=1);
namespace App\Grid;
use App\Entity\User;
use Sylius\Bundle\GridBundle\Builder\Filter\ExistsFilter;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;
use Sylius\Bundle\GridBundle\Grid\AbstractGrid;
use Sylius\Component\Grid\Attribute\AsGrid;
#[AsGrid(
resourceClass: User::class,
name: 'app_user',
)]
final class UserGrid extends AbstractGrid
{
public function __invoke(GridBuilderInterface $gridBuilder): void
{
$gridBuilder
->withFilters(
Filter::create('date', 'exists')
->setOptions(['field' => 'completedAt'])
)
// can be simplified using ExistsFilter
->withFilters(
ExistsFilter::create('date', 'completedAt')
)
;
}
}
<?php
use Sylius\Bundle\GridBundle\Builder\Filter\ExistsFilter;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\GridBuilder;
use Sylius\Bundle\GridBundle\Config\GridConfig;
return static function (GridConfig $grid): void {
$grid->addGrid(GridBuilder::create('app_user', '%app.model.user.class%')
->withFilters(
Filter::create('date', 'exists')
->setOptions(['field' => 'completedAt'])
)
// can be simplified using ExistsFilter
->withFilters(
ExistsFilter::create('date', 'completedAt')
)
)
};
src/Grid/UserGrid.php
<?php
declare(strict_types=1);
namespace App\Grid;
use App\Entity\User;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\Filter\SelectFilter;
use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;
use Sylius\Bundle\GridBundle\Grid\AbstractGrid;
use Sylius\Component\Grid\Attribute\AsGrid;
#[AsGrid(
resourceClass: User::class,
name: 'app_user',
)]
final class UserGrid extends AbstractGrid
{
public function __invoke(GridBuilderInterface $gridBuilder): void
{
$gridBuilder
->withFilters(
Filter::create('state', 'select')
->setFormOptions([
'choices' => [
'sylius.ui.ready' => 'Ready',
'sylius.ui.shipped' => 'Shipped',
],
])
)
// can be simplified using SelectFilter
->withFilters(
SelectFilter::create('state', [
'sylius.ui.ready' => 'Ready',
'sylius.ui.shipped' => 'Shipped',
])
)
;
}
}
<?php
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\Filter\SelectFilter;
use Sylius\Bundle\GridBundle\Builder\GridBuilder;
use Sylius\Bundle\GridBundle\Config\GridConfig;
return static function (GridConfig $grid): void {
$grid->addGrid(GridBuilder::create('app_user', '%app.model.user.class%')
->withFilters(
Filter::create('state', 'select')
->setFormOptions([
'choices' => [
'sylius.ui.ready' => 'Ready',
'sylius.ui.shipped' => 'Shipped',
],
])
)
// can be simplified using SelectFilter
->withFilters(
SelectFilter::create('state', [
'sylius.ui.ready' => 'Ready',
'sylius.ui.shipped' => 'Shipped',
])
)
)
};
src/Grid/Filter/SuppliersStatisticsFilter.php
<?php
declare(strict_types=1);
namespace App\Grid\Filter;
use App\Form\Type\Filter\SuppliersStatisticsFilterType;
use Sylius\Bundle\GridBundle\Doctrine\DataSourceInterface;
use Sylius\Component\Grid\Attribute\AsFilter;
use Sylius\Component\Grid\Filtering\FilterInterface;
#[AsFilter(
formType: SuppliersStatisticsFilterType::class, // (custom) Symfony FormType
template: '@SyliusBootstrapAdminUi/shared/grid/filter/select.html.twig', // or you can use your own Twig template
type: 'suppliers_statistics', // optional - FQCN by default
)]
class SuppliersStatisticsFilter implements FilterInterface
{
public function apply(DataSourceInterface $dataSource, $name, $data, array $options = []): void
{
// Your filtering logic.
// $data['stats'] contains the submitted value!
$queryBuilder = $dataSource->getQueryBuilder();
$queryBuilder
->andWhere('stats = :stats')
->setParameter(':stats', $data['stats'])
;
// You can leverage the ExpressionBuilder to apply driver-agnostic filters to the data source.
// Combined with restrict(), it provides query builderβstyle functionalities for grid filters.
$dataSource->restrict($dataSource->getExpressionBuilder()->equals('stats', $data['stats']));
}
}
<?php
namespace App\Form\Type\Filter;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class SuppliersStatisticsFilterType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add(
'stats',
ChoiceType::class,
['choices' => range($options['range'][0], $options['range'][1])]
);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver
->setDefaults([
'range' => [0, 10],
])
->setAllowedTypes('range', ['array'])
;
}
}
src/Grid/Filter/SuppliersStatisticsFilter.php
<?php
namespace App\Grid\Filter;
use App\Form\Type\Filter\SuppliersStatisticsFilterType;
use Sylius\Bundle\GridBundle\Doctrine\DataSourceInterface;
use Sylius\Component\Grid\Filtering\ConfigurableFilterInterface;
class SuppliersStatisticsFilter implements ConfigurableFilterInterface
{
public function apply(DataSourceInterface $dataSource, $name, $data, array $options = []): void
{
// Your filtering logic.
// $data['stats'] contains the submitted value!
$queryBuilder = $dataSource->getQueryBuilder();
$queryBuilder
->andWhere('stats = :stats')
->setParameter(':stats', $data['stats'])
;
// For driver abstraction you can use the expression builder. ExpressionBuilder is a kind of query builder.
$dataSource->restrict($dataSource->getExpressionBuilder()->equals('stats', $data['stats']));
}
public static function getType() : string
{
return 'suppliers_statistics';
}
public static function getFormType() : string
{
return SuppliersStatisticsFilterType::class;
}
}
src/Grid/Filter/SuppliersStatisticsFilterType.php
<?php
namespace App\Form\Type\Filter;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class SuppliersStatisticsFilterType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add(
'stats',
ChoiceType::class,
['choices' => range($options['range'][0], $options['range'][1])]
);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver
->setDefaults([
'range' => [0, 10],
])
->setAllowedTypes('range', ['array'])
;
}
}
<?php
use App\Entity\Tournament;
use Sylius\Bundle\GridBundle\Builder\Action\Action;
use Sylius\Bundle\GridBundle\Builder\ActionGroup\ItemActionGroup;
use Sylius\Bundle\GridBundle\Builder\GridBuilder;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Config\GridConfig;
return static function (GridConfig $grid) {
$grid->addGrid(GridBuilder::create('app_tournament', Tournament::class)
->withFilters(
Filter::create('stats', 'suppliers_statistics')
->setFormOptions(['range' => [0, 100]])
)
)
};
src/Grid/TournamentGrid.php
<?php
declare(strict_types=1);
namespace App\Grid;
use App\Entity\Tournament;
use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;
use Sylius\Bundle\GridBundle\Grid\AbstractGrid;
#[AsGrid(
name: 'app_tournament',
resourceClass: Tournament::class,
)]
final class TournamentGrid extends AbstractGrid
{
public function __invoke(GridBuilderInterface $gridBuilder): void
{
$gridBuilder
->withFilters(
Filter::create('stats', 'suppliers_statistics')
->setFormOptions(['range' => [0, 100]])
)
;
}
}
config/packages/sylius_grid.yaml
sylius_grid:
grids:
app_tournament:
driver: doctrine/orm
resource: app.tournament
filters:
stats:
type: suppliers_statistics
form_options:
range: [0, 100]
templates: # only needed if you didn't use AsFilter attribute
filter:
suppliers_statistics: '@App/Grid/Filter/suppliers_statistics.html.twig'