- Documentation >
- PIM (Product management) >
- Customize PIM >
- Create custom catalog filter
Create custom catalog filter
Catalog filters let you narrow down the products from the PIM that are available in the given catalog.
Besides the built-in catalog filters, you can also create custom ones.
The following example shows how to create a filter that selects products with the entered name.
Create filter class
To create a custom catalog filter, first you need to create a filter class in App\CatalogFilter\ProductNameFilter
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 | <?php
declare(strict_types=1);
namespace App\CatalogFilter;
use Ibexa\Contracts\ProductCatalog\CatalogFilters\FilterDefinitionInterface;
use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\ProductName;
use Ibexa\Contracts\ProductCatalog\Values\Product\Query\CriterionInterface;
final class ProductNameFilter implements FilterDefinitionInterface
{
public function getIdentifier(): string
{
return 'product_name';
}
public function getName(): string
{
return 'Product name';
}
public function supports(CriterionInterface $criterion): bool
{
return $criterion instanceof ProductName;
}
public static function getTranslationMessages(): array
{
return [];
}
public function getGroupName(): string
{
return 'Custom filters';
}
}
|
The filter must implement Ibexa\Contracts\ProductCatalog\CatalogFilters\FilterDefinitionInterface
, provide the filter identifier and name, and the group in which it's displayed in the editing menu.
The example above uses the built-in ProductName
Search Criterion.
Next, you need to add a form mapper: ProductNameFilterFormMapper
that maps the input from the filter form to the data model:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 | <?php
declare(strict_types=1);
namespace App\CatalogFilter;
use Ibexa\Bundle\ProductCatalog\Form\Type\TagifyType;
use Ibexa\Contracts\ProductCatalog\CatalogFilters\FilterDefinitionInterface;
use Ibexa\Contracts\ProductCatalog\CatalogFilters\FilterFormMapperInterface;
use Symfony\Component\Form\FormBuilderInterface;
final class ProductNameFilterFormMapper implements FilterFormMapperInterface
{
public function __construct()
{
}
public function createFilterForm(
FilterDefinitionInterface $filterDefinition,
FormBuilderInterface $builder,
array $context = []
): void {
$builder->add(
$filterDefinition->getIdentifier(),
TagifyType::class,
[
'label' => 'Product name',
'block_prefix' => 'catalog_criteria_product_name',
'translation_domain' => 'product_catalog',
]
);
$builder->get($filterDefinition->getIdentifier())
->addModelTransformer(
new DataTransformer\ProductNameCriterionTransformer()
);
}
public function supports(FilterDefinitionInterface $filterDefinition): bool
{
return $filterDefinition instanceof ProductNameFilter;
}
}
|
The filter can use the built-in ProductName
Criterion, but you still need a data transformer for the data entered when editing the catalog (line 35).
Before you add a data transformer, register the required services.
Register services
Register the filter and its mapper as services.
Tag the filter with ibexa.product_catalog.catalog_filter
and the form mapper with ibexa.product_catalog.catalog_filter.form_mapper
:
| services:
App\CatalogFilter\ProductNameFilter:
tags:
- name: ibexa.product_catalog.catalog_filter
alias: product_name
App\CatalogFilter\ProductNameFilterFormMapper:
tags:
- name: ibexa.product_catalog.catalog_filter.form_mapper
|
Now, create ProductNameCriterionTransformer
in src/CatalogFilter/DataTransformer
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 | <?php
declare(strict_types=1);
namespace App\CatalogFilter\DataTransformer;
use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\ProductName;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
final class ProductNameCriterionTransformer implements DataTransformerInterface
{
public function transform($value): ?string
{
if (null === $value) {
return null;
}
if (!$value instanceof ProductName) {
throw new TransformationFailedException('Expected a ' . ProductName::class . ' object.');
}
return $value->getName();
}
public function reverseTransform($value): ?ProductName
{
if ($value === null) {
return null;
}
if (!is_string($value)) {
throw new TransformationFailedException('Invalid data, expected a string value');
}
return new ProductName($value);
}
}
|
Provide templates
Now, provide the templates for the catalog editing view in the back office.
You need two templates: one for the filter form, and one for the filter badge in the product list.
First, add a form_field_override.html.twig
template to templates/themes/admin/product_catalog
:
| {% extends '@ibexadesign/product_catalog/form_fields.html.twig' %}
{%- block catalog_criteria_product_name_row -%}
{{- block('catalog_taggify_panel') -}}
{%- endblock -%}
|
Here, you use the same built-in template that is used for example for the product code filter.
It's placed in a template block corresponding to your custom filter, catalog_criteria_product_name_values
.
To ensure the template is used as a back office form theme, add the following configuration:
| twig:
form_themes:
- '@ibexadesign/product_catalog/form_field_override.html.twig'
|
Next, add a template that handles the display of the filter badge on the list of the currently filtered products.
Add catalog_filters_blocks.html.twig
to templates/themes/admin/product_catalog
:
| {% block catalog_criteria_product_name_values %}
{% include '@ibexadesign/product_catalog/catalog/edit/list_filter_taggify.html.twig' with { criteria } %}
{% endblock %}
|
To ensure this template is used to render the catalog filter form, add the following configuration:
| ibexa:
system:
default:
product_catalog:
catalogs:
filter_preview_templates:
- { template: "@ibexadesign/product_catalog/catalog_filters_blocks.html.twig", priority: 10 }
|
Check results
Finally, you can check the results.
Go to Product catalog -> Catalogs and create a new catalog.
From the filter list, select Product name, type the name of an existing product and click Save.
