Magento 2: Filter Custom Column in Admin Grid
-
10-03-2021 - |
Question
I have a custom column in an admin grid, this column is populated with a custom renderer and is not actually saved to the database. Is it possible to still filter by this column?
in my Grid.php file:
$this->addColumn(
'test_column', [
'header' => __('Test Column'),
'index' => 'test_column',
'renderer' => 'Company\Module\Block\StockMovement\Renderer\Test',
'filter_condition_callback' => array($this, '_myTestFilter')
]
);
...
protected function _myTestFilter($collection, $column)
{
if (!$value = $column->getFilter()->getValue()) {
return $this;
}
$collection->getSelect()->where("test_column like ?", "%$value%");
return $this;
}
And then here is my "Test.php" Renderer file:
<?php
namespace Company\Module\Block\StockMovement\Renderer;
use Magento\Framework\DataObject;
class Test extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer
{
public function render(DataObject $row)
{
$comments = $row->getsm_comments();
if ($comments) {
return 'abc';
} else {
return 'xyz';
}
}
}
So now in my custom column on my grid with either abc
or xyz
text values. These are not actually saved in the DB but just rendered text. How can I filter using this column's text?
Solution
UPDATED (2) ANSWER: If you want to use the same logic in your renderer to filter the column, removing items from the collection based on your custom renderer logic can be a option:
EDIT: Moved filtering before collection set to widget to have pager working.
protected function _prepareCollection()
{
...
//add following before setCollection called
if ($this->getTestColumnFilter() !== null) {
$collection = $this->_addCustomFilterToCollection($collection);
}
...
$this->setCollection($collection);
}
protected function _prepareColumns()
{
...
//add a filter_condition_callback pointing to an empty function to prevent default filtering that will cause an error like *'test_column not found'*
$this->addColumn(
'test_column', [
'header' => __('Test Column'),
'index' => 'test_column',
'renderer' => 'Company\Module\Block\StockMovement\Renderer\Test',
'filter_condition_callback' => array($this, '_preventDefaultFilter')
]
);
...
}
/**
* @param $collection
* @param $column
* @return $this
*/
public function _preventDefaultFilter($collection, $column)
{
return $this;
}
/**
* Get test_column filter from request using the same method in grid widget
*
* @return mixed|null
*/
private function getTestColumnFilter()
{
$filter = $this->getParam($this->getVarNameFilter(), null);
if ($filter === null) {
$filter = $this->_defaultFilter;
}
if (is_string($filter)) {
$data = $this->_backendHelper->prepareFilterString($filter);
$data = array_merge($data, (array)$this->getRequest()->getPost($this->getVarNameFilter()));
} elseif ($filter && is_array($filter)) {
$data = $filter;
} elseif (0 !== sizeof($this->_defaultFilter)) {
$data = $this->_defaultFilter;
}
if (array_key_exists('test_column', $data)) {
return $data['test_column'];
}
return null;
}
/**
* Add our custom filter based on renderer logic
*
* @param $collection
* @return \Magento\Framework\Data\CollectionDataSourceInterface
*/
private function _addCustomFilterToCollection($collection)
{
foreach ($collection->getItems() as $key => $row) {
//renderer logic here
$comments = $row->getId() % 2 == 1;
if ($comments) {
$renderedValue = 'abc';
} else {
$renderedValue = 'xyz';
}
$filterValue = $this->getTestColumnFilter();
//remove item from collection if filter value is not equal to rendered value
if ($filterValue !== $renderedValue){
$collection->addFieldToFilter(
"{$this->getMainTableAlias($collection)}.{$row->getIdFieldName()}",
['neq' => $row->getId()]
);
}
}
return $collection;
}
/**
* Identify main table alias or its name if alias is not defined.
*
* @param $collection
* @return string
*/
private function getMainTableAlias($collection)
{
foreach ($collection->getSelect()->getPart(\Magento\Framework\DB\Select::FROM) as $tableAlias => $tableMetadata) {
if ($tableMetadata['joinType'] == 'from') {
return $tableAlias;
}
}
return 'main_table';
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange