Events
Events List
Datagrids in Oro applications are highly customizable. It is possible to modify an existing grid to fetch more data than initially defined in the grid configuration.
To provide extendability points, build
and result
events have been introduced.
Build Events
Build events are dispatched by the Builder
class right before and immediately after processing the configuration and building datasource. They are helpful in case you need to modify the datagrid or a query configuration.
Four events are dispatched during the build process:
Class
BuildBefore
, event name:oro_datagrid.datagrid.build.before
Class
BuildBefore
, event name:oro_datagrid.datagrid.build.before.DATAGRID_NAME
Class
BuildAfter
, event name:oro_datagrid.datagrid.build.after
Class
BuildAfter
, event name:oro_datagrid.datagrid.build.after.DATAGRID_NAME
BuildBefore Events
By listening to these events, you can add new elements to the grid configuration or modify the already existing configuration in your event listener.
You can use the generic build.before
event to listen to all or specific datagrids, which will be called only for the given datagrid - build.before.DATAGRID_NAME
.
The BuildBefore
event class has access to the DatagridConfiguration instance.
Hint
Please note that at this point datasource has not been initialized yet, therefore calling $event->getDatagrid()->getDatasource()
returns null
.
As an illustration, let’s add one more column to a specific datagrid. For this, create an event listener and modify the existing configuration in the following way:
namespace Acme\Bundle\DemoBundle\EventListener\Datagrid;
use Oro\Bundle\DataGridBundle\Event\BuildBefore;
class AdditionalColumnDatagridListener
{
/**
* @param BuildBefore $event
* @return void
*/
public function onBuildBefore(BuildBefore $event): void
{
$config = $event->getConfig();
$config->offsetSetByPath('[columns][myCustomColumn]', ['label' => 'acme.demo.my_custom_column.label']);
$config->offsetAddToArrayByPath('[source][query][select]', ['123 as myCustomColumn']);
}
}
Once the listener is created, register it in services.yml:
acme_demo.event_listener.datagrid.additional_column:
class: Acme\Bundle\DemoBundle\EventListener\Datagrid\AdditionalColumnDatagridListener
tags:
- { name: kernel.event_listener, event: oro_datagrid.datagrid.build.before.DATAGRID_NAME, method: onBuildBefore }
Use Cases
Add additional columns and update query configuration for the translation datagrid:
Oro\Bundle\TranslationBundle\EventListener\Datagrid\LanguageListener
Remove
public
column from the system calendar datagrid:Oro\Bundle\CalendarBundle\EventListener\Datagrid\SystemCalendarGridListener
(OroCommerce) Bind user’s currency parameter to the checkout grid:
Oro\Bundle\CheckoutBundle\Datagrid\CheckoutGridListener
BuildAfter Events
You can modify the datasource or even the whole datagrid instance by listening to these events. However, the most common case for
this event is to modify the query (add additional joins, selects, the where
conditions, etc.).
You can use a generic build.after
event for listening to all or specific datagrids, which will be called
only for a given datagrid - build.after.DATAGRID_NAME
.
The BuildAfter
event class has access to Datagrid instance.
For example, let us filter the datagrid by a particular value from the request params. For this, create an event listener and modify the query builder, as illustrated below:
namespace Acme\Bundle\DemoBundle\EventListener\Datagrid;
use Oro\Bundle\DataGridBundle\Datasource\Orm\OrmDatasource;
use Oro\Bundle\DataGridBundle\Event\BuildAfter;
use Symfony\Component\HttpFoundation\RequestStack;
class FilterByRequestParamListener
{
protected RequestStack $requestStack;
/**
* @param RequestStack $requestStack
*/
public function __construct(RequestStack $requestStack) {
$this->requestStack = $requestStack;
}
/**
* @param BuildAfter $event
* @return void
*/
public function onBuildAfter(BuildAfter $event): void
{
$datasource = $event->getDatagrid()->getDatasource();
if (!$datasource instanceof OrmDatasource) {
return;
}
$customFilter = $this->requestStack->getCurrentRequest()->get('custom_filter');
$queryBuilder = $datasource->getQueryBuilder();
$queryBuilder->andWhere($queryBuilder->expr()->eq('some_column', ':custom_filter'));
$queryBuilder->setParameter('custom_filter', $customFilter);
}
}
Please note that this example works only for ORM datasources.
Once the listener is created, register it in services.yml
:
acme_demo.event_listener.datagrid.filter_by_request_param:
class: Acme\Bundle\DemoBundle\EventListener\Datagrid\FilterByRequestParamListener
arguments:
- '@request_stack'
tags:
- { name: kernel.event_listener, event: oro_datagrid.datagrid.build.after.DATAGRID_NAME, method: onBuildAfter }
Use Cases
Apply additional filtering to the activity email grid:
Oro\Bundle\EmailBundle\EventListener\Datagrid\ActivityGridListener
(OroCommerce) Add additional properties to the storefront product grid:
Oro\Bundle\CatalogBundle\EventListener\SearchCategoryFilteringEventListener
Result Events
Result events are type-specific, which means that datasource
is responsible for dispatching them.
Listening to these events is useful both when you need to access a query (e.g., ORM, search) and modify the results.
As an example, have a look at the OrmDatasource. In the getResult()
method it dispatches 4 main and 2 additional events:
Additional - Class
OrmResultBeforeQuery
, event name:oro_datagrid.orm_datasource.result.before_query
Additional - Class
OrmResultBeforeQuery
, event name:oro_datagrid.orm_datasource.result.before_query.DATAGRID_NAME
Main - Class
OrmResultBefore
, event name:oro_datagrid.orm_datasource.result.before
Main - Class
OrmResultBefore
, event name:oro_datagrid.orm_datasource.result.before.DATAGRID_NAME
Main - Class
OrmResultAfter
, event name:oro_datagrid.orm_datasource.result.after
Main - Class
OrmResultAfter
, event name:oro_datagrid.orm_datasource.result.after.DATAGRID_NAME
The first four events are mostly used to access a query at different stages, while the last two are used to modify the results.
Remember to dispatch result events when creating your own custom datasource type.
ResultBefore Events
The purpose of these events is to have the ability to access datagrid or a query instance before the datasource starts building the results.
You can use generic result.before
event for listening to all or specific datagrids, which will be called only for a given datagrid - result.before.DATAGRID_NAME
.
Use Cases
Apply ACL to a datagrid datasource:
Oro\Bundle\DataGridBundle\EventListener\OrmDatasourceAclListener
ResultAfter Events
The purpose of these events is to have ability to modify data after the rows were fetched from the datasource
.
You can use generic result.after
event for listening to all or specific datagrids, which will be called
only for a given datagrid - result.after.DATAGRID_NAME
.
For instance, if you have complex data that is hard to process with the standard datagrid configuration using YML files,
you can create an event listener and fetch the data once the rows are fetched from the datasource
.
namespace Acme\Bundle\DemoBundle\EventListener\Datagrid;
use Oro\Bundle\DataGridBundle\Datasource\ResultRecord;
use Oro\Bundle\DataGridBundle\Event\OrmResultAfter;
class ComplexDataDatagridListener
{
/**
* @param OrmResultAfter $event
* @return void
*/
public function onResultAfter(OrmResultAfter $event): void
{
/** @var ResultRecord[] $records */
$records = $event->getRecords();
$complexData = $this->complexService->getComplexDataForRecords($records);
foreach ($records as $record) {
$recordId = $record->getValue('id');
$record->addData(['complexData' => $complexData[$recordId]]);
}
}
}
Once the event listener is created, register it in services.yml
:
acme_demo.event_listener.datagrid.complex_data:
class: Acme\Bundle\DemoBundle\EventListener\Datagrid\ComplexDataDatagridListener
tags:
- { name: kernel.event_listener, event: oro_datagrid.orm_datasource.result.after.DATAGRID_NAME, method: onResultAfter }
Use Cases
Translate workflow fields in the email notification grid:
Oro\Bundle\WorkflowBundle\Datagrid\EmailNotificationDatagridListener
(OroCommerce) Add payment methods to the order grid:
Oro\Bundle\OrderBundle\EventListener\OrderDatagridListener