Skip to content

Commit

Permalink
OD-117: Review Book and Cookbook
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Kuzmenko committed Aug 1, 2015
1 parent 2c82105 commit de1c28d
Showing 1 changed file with 108 additions and 73 deletions.
181 changes: 108 additions & 73 deletions cookbook/how_to_pass_request_parameter_to_grid.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,114 @@ For example:
Our goal is to set :contactId parameter with the value from the request.

Solution 1. Create custom event listener
----------------------------------------
Solution 1: Grid Parameter binding
----------------------------------

The easiest way that should be sufficient for most situations is to use parameter binding option in of the datasource
to configure mapping between datagrid and query parameters.

You can do this by adding the ``bind_parameters`` option to your ``datagrid.yml`` using the following syntax:

.. code-block:: yaml
:linenos:
# src/Acme/Bundle/TaskBundle/Resources/config/datagrid.yml
datagrid:
# ...
acme-tasks-grid:
# ...
source:
query:
where:
and:
- task.relatedContact = :contactId
bind_parameters:
# Get the "contactId" parameter from the datagrid
# and set its value to the "contactId" parameter in the datasource query
- contactId
# ...
# ...
In case if names of the parameter in the grid and the query do not match you can pass associative array of parameters,
where the key will be the name of the query parameter, and the value will match the name of the parameter in the grid:

.. code-block:: yaml
:linenos:
# src/Acme/Bundle/TaskBundle/Resources/config/datagrid.yml
datagrid:
# ...
acme-tasks-grid:
# ...
source:
query:
where:
and:
- task.relatedContact = :contactId
bind_parameters:
# Get the "relatedContactId" parameter from the datagrid
# and set its value to the "contactId" parameter in the datasource query
contactId: relatedContactId
# ...
# ...
.. caution::

A datasource must implement the ``Oro\Bundle\DataGridBundle\Datasource\ParameterBinderAwareInterface``
to support the ``bind_parameters`` option.

We need to create a listener for the "oro_datagrid.datagrid.build.after" event
and set the parameter for the source query in this listener. Also we need to pass the parameter to the grid.
Now we need to pass the parameter with name "relatedContactId" to our grid.
The controller receives a contact entity and passes it to the view:

.. code-block:: php
:linenos:
<?php
// src/Acme/Bundle/TaskBundle/Controller/TaskController.php
namespace Acme\Bundle\TaskBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use OroCRM\Bundle\ContactBundle\Entity\Contact;
class TaskController extends Controller
{
// ...
/**
* @Route("/contact/{id}/tasks", name="acme_task_contact_tasks", requirements={"id"="\d+"})
* @Template
*/
public function contactTasksAction(Contact $contact)
{
return array('contact' => $contact);
}
// ...
}
The view passes the "relatedContactId" parameter to the grid:
.. code-block:: html+jinja
:linenos:

{# src/Acme/Bundle/TaskBundle/Resources/views/Task/contactTasks.html.twig #}
{% import 'OroDataGridBundle::macros.html.twig' as dataGrid %}

<div class="widget-content">
{{ dataGrid.renderGrid('acme-tasks-grid', {relatedContactId: contact.id}) }}
</div>

Solution 2. Create custom event listener
----------------------------------------

Listener class code:
If the first example does not work for you for some reason (datasource does not support parameters binding,
you need to implement additional logic before binding parameters, etc.), you can create a listener for the
``oro_datagrid.datagrid.build.after`` event and set the parameter for the source query in this listener:

.. code-block:: php
:linenos:
Expand Down Expand Up @@ -93,74 +194,8 @@ Register this listener in the container:
tags:
- { name: kernel.event_listener, event: oro_datagrid.datagrid.build.after.acme-tasks-grid, method: onBuildAfter }
Now we need to pass the parameter with name "contactId" to our grid.
The controller receives a contact entity and passes it to the view:

.. code-block:: php
:linenos:
<?php
// src/Acme/Bundle/TaskBundle/Controller/TaskController.php
namespace Acme\Bundle\TaskBundle\EventListener;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use OroCRM\Bundle\ContactBundle\Entity\Contact;
class TaskController extends Controller
{
// ...
/**
* @Route("/contact/{id}/tasks", name="acme_task_contact_tasks", requirements={"id"="\d+"})
* @Template
*/
public function contactTasksAction(Contact $contact)
{
return array('contact' => $contact);
}
// ...
}
The view passes "contactId" parameter to the grid, it will be used in the listener:

.. code-block:: html+jinja
:linenos:

{# src/Acme/Bundle/TaskBundle/Resources/views/Task/contactsTask.html.twig #}
{% import 'OroDataGridBundle::macros.html.twig' as dataGrid %}

<div class="widget-content">
{{ dataGrid.renderGrid('acme-tasks-grid', {contactId: contact.id}) }}
</div>


Solution 2. Use existing listener
---------------------------------

Instead of writing your custom listener you can use the existing class
(``Oro\Bundle\DataGridBundle\EventListener\BaseOrmRelationDatagridListener``) that can be referenced in the service configuration
via ``oro_datagrid.event_listener.base_orm_relation.class`` parameter:

.. code-block:: yaml
:linenos:
# src/Acme/Bundle/TaskBundle/Resources/config/services.yml
services:
acme_task.event_listener.acme_tasks_grid_parameter_listener:
class: %oro_datagrid.event_listener.base_orm_relation.class%
arguments:
- contactId
- false
tags:
- { name: kernel.event_listener, event: oro_datagrid.datagrid.build.after.acme-tasks-grid, method: onBuildAfter }
This way the listener is reused and you don't need to write one of your own, but you still need to pass the "contactId" parameter
to the grid (see example with passing parameters to the grid from a Twig template).
Remember that you still need to pass the "relatedContactId" parameter to the grid to the grid from a Twig template
(see example in the previous solution).

References
----------
Expand Down

0 comments on commit de1c28d

Please sign in to comment.