The purpose of this bundle is providing a way to get some filters, that stay in session, to be able to use them when displaying a list of items. It also supports sorting.
Run composer require pugx/filter-bundle
. No configuration is required.
Inject provided service in your controller and use it with a form.
Your form should use GET
as method, use some fields that make sense on your list of item,
and not use CSRF protection.
First step is to save filter with a name (if form is submitted). Then, you can get
a key/value array in $filter->filter('foo')
, where "foo" is the name you provided above.
Using such array to retrieve filtered value is up to you: this bundle makes no assumptions on your domain and doesn't do magic.
Here is an example:
<?php
class FooController extends AbstractController
{
public function itemList(Repository $repository, Filter $filter): Response
{
if ($filter->saveFilter(Form\FooFilterType::class, 'foo')) {
return $this->redirectToRoute('foo_item_list');
}
// this is just an example: please implement your own method
$foos = $repository->getList($filter->filter('foo'));
return $this->render('foo/item_list.html.twig', [
'form' => $filter->getFormView('foo'),
'foos' => $foos,
]);
}
}
{# this will display your form. Use '_pugx_filter_b4.html.twig' or '_pugx_filter_b5.html.twig' for Bootstrap 4 / 5 #}
{{ include('_pugx_filter.html.twig' with {name: 'foo'}) }}
{% for foo in foos %}
{# here you can display your list of filtered items, as long as you did your homework #}
{% endfor %}
<?php
class FooFilterType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', Type\TextType::class, ['required' => false])
->add('email', Type\TextType::class, ['required' => false])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'csrf_protection' => false,
'method' => 'GET',
]);
}
}
You can use provided Twig extension for column sorting functionality.
Example of template:
{# Use '_pugx_sort_b4.html.twig' or '_pugx_sort_b5.html.twig' for Bootstrap 4 / 5 #}
{% from '_pugx_sort.html.twig' import sort -%}
{% block body %}
{{ include('_pugx_filter.html.twig' with {name: 'foo'}) }}
<table class="table">
<thead>
<tr>
<th scope="col">Name {{ sort('my_sorting_route', 'foo', 'name') }} </th>
</tr>
</thead>
<tbody>
{% for foo in foos %}
{# same as above... #}
{% endfor %}
</tbody>
</table>
{% endblock %}
You need to provide a route/action to perform sorting, using $filter->sort('foo', $field, $direction)
.
Then, you'll find an addtional value inside your filter array, like this:
$filters = [
'_sort' => [
'field' => 'name',
'direction' => 'ASC',
]
];
You can use this value to perform your sorting (again, this is up to you and it depends on your domain logic).
Translations are available (for now, only for English/French/Italian).
If you're using Symfony 4.4+, translatons should be automatically discovered.
On older Symfony versions, add this to your configuration:
# config/packages/translation.yaml
framework:
translator:
paths:
- '%kernel.project_dir%/translations/' # this line should be already present
- '%kernel.project_dir%/vendor/pugx/filter-bundle/translations/' # add this line
A jQuery helper is provided, to enhance UX. You can use it by requiring the following line in your package.json file:
{
"dependencies": {
"@pugx/filter-bundle": "file:vendor/pugx/filter-bundle/assets"
}
}
Then you can do something like the following:
// assets/js/app.js
import '@pugx/filter-bundle/js/filter';
$(document).ready(function () {
'use strict';
if (jQuery().pugxFilter) {
$('#filter').pugxFilter();
}
});
The basic results will be that icon in the toggle button will be toggled along, and the arrow will point to right when filters are shown (and back to bottom when filters are collapsed).
You can pass an option object to pugxFilter
function.
Currently supported options are:
callbackHide
a callback to be used when filters are collapsedcallbackShow
a callback to be used when filters are shown
If you prefer vanilla js with Bootstrap, you can use the following snippet:
import Collapse from "bootstrap/js/src/collapse";
let collapses = document.querySelectorAll("[data-bs-toggle='collapse']");
Array.from(collapses, (collapse) => {
new Collapse(collapse);
let filter = document.getElementById("filter");
if (filter) {
filter.addEventListener("hide.bs.collapse", () => {
let icon = collapse.querySelector("button.filter svg, button.filter i");
icon && icon.classList.remove("fa-angle-right");
icon && icon.classList.add("fa-angle-down");
});
filter.addEventListener("show.bs.collapse", () => {
let icon = collapse.querySelector("button.filter svg, button.filter i");
icon && icon.classList.remove("fa-angle-down");
icon && icon.classList.add("fa-angle-right");
});
}
});
Following helper functions are available as functions in twig templates:
filter_has
: tells if a filter is enabled (e.g. if a session for filter exists)filter_is
: tells if a filter field is selectedfilter_is_not
: tells if a filter field is not selected