How to use FilterPool and Collection using the FilterApplierInterface
-
11-12-2020 - |
Question
Hi fellow Magento developers!
I'm currently trying to figure out how to use the FilterPool with classes instead of using it with the etc/di.xml.
It should be possible to use filters in a grid listing without setting up a di.xml virtual provider, however, I can't seem to work out how..
How I understand it now is like this:
You have a class, say Supplier
, and you want it to be the DataProvider
for given listing supplier_listing.xml
, I also want to be able to apply Filter
's to it, therefore i'm going to implement the interface FilterApplierInterface
, which requires me to implement a method called apply()
.
However, the apply()
method requires a Collection
object and a Filter
object, and this is where I get lost, how can I specify which data to apply and what Filter to use? Do I need to call the apply()
method myself or should the Magento framework do this for me? If so, how can I tell Magento which Collection to use and what Filter to apply?
Any help would be appreciated, as I'm at a loss right now..
On a side note, i've used the di.xml virtual providers, however, I want to learn more about how Magento does it and how to do it yourself without the virtuals. Any help would be greatly appreciated!
Solution
Maybe not exact answer but it works.
Case though XML
There is an answer in magento2/module-cms
.
Basically, there is responsible configuration for that:
<virtualType name="CmsGirdFilterPool" type="Magento\Framework\View\Element\UiComponent\DataProvider\FilterPool">
<arguments>
<argument name="appliers" xsi:type="array">
<item name="regular" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\RegularFilter</item>
<item name="fulltext" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\FulltextFilter</item>
</argument>
</arguments>
</virtualType>
I didn't find a usage of CmsGirdFilterPool
but you may try to use this example of Adminhtml Grid implementation.
Case thought PHP code
Also, I found out a simple non-XML way to use "fulltext" filter by customizing method \Magento\Ui\DataProvider\AbstractDataProvider::addFilter()
.
namespace Vendor\ModuleName\Ui\Component;
use Magento\Framework\Api\Filter;
use Magento\Framework\View\Element\UiComponent\DataProvider\FilterApplierInterface;
use Magento\Framework\View\Element\UiComponent\DataProvider\FulltextFilterFactory;
use Magento\Ui\DataProvider\AbstractDataProvider;
/**
* Class GridDataProvider
*/
class GridDataProvider extends AbstractDataProvider
{
/**
* Fulltext filter
*
* @var FilterApplierInterface
*/
protected $fulltextFilter;
/**
* Construct
*
* @param string $name
* @param string $primaryFieldName
* @param string $requestFieldName
* @param object $collectionFactory
* @param FulltextFilterFactory $fulltextFilter
* @param array $meta
* @param array $data
*/
public function __construct(
$name,
$primaryFieldName,
$requestFieldName,
$collectionFactory,
FulltextFilterFactory $fulltextFilter,
array $meta = [],
array $data = []
) {
parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
$this->collection = $collectionFactory->create();
$this->fulltextFilter = $fulltextFilter->create();
}
/**
* Add processing fulltext query
*
* Some workaround for fulltext search.
*
* @param Filter $filter
* @return void
*/
public function addFilter(Filter $filter)
{
if ('fulltext' == $filter->getField()) {
$this->fulltextFilter->apply($this->collection, $filter);
} else {
parent::addFilter($filter);
}
}
/**
* Get data
*
* @return array
*/
public function getData()
{
if (!$this->getCollection()->isLoaded()) {
$this->getCollection()->load();
}
return $this->getCollection()->toArray();
}
}