action_list.rst 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. The List View
  2. =============
  3. .. note::
  4. This document is a stub representing a new work in progress. If you're reading
  5. this you can help contribute, **no matter what your experience level with Sonata
  6. is**. Check out the `issues on GitHub`_ for more information about how to get involved.
  7. This document will cover the List view which you use to browse the objects in your
  8. system. It will cover configuration of the list itself and the filters you can use
  9. to control what's visible.
  10. Basic configuration
  11. -------------------
  12. SonataAdmin Options that may affect the list view:
  13. .. code-block:: yaml
  14. sonata_admin:
  15. templates:
  16. list: SonataAdminBundle:CRUD:list.html.twig
  17. action: SonataAdminBundle:CRUD:action.html.twig
  18. select: SonataAdminBundle:CRUD:list__select.html.twig
  19. list_block: SonataAdminBundle:Block:block_admin_list.html.twig
  20. short_object_description: SonataAdminBundle:Helper:short-object-description.html.twig
  21. batch: SonataAdminBundle:CRUD:list__batch.html.twig
  22. inner_list_row: SonataAdminBundle:CRUD:list_inner_row.html.twig
  23. base_list_field: SonataAdminBundle:CRUD:base_list_field.html.twig
  24. pager_links: SonataAdminBundle:Pager:links.html.twig
  25. pager_results: SonataAdminBundle:Pager:results.html.twig
  26. .. note::
  27. **TODO**:
  28. * a note about Routes and how disabling them disables the related action
  29. * adding custom columns
  30. Customizing the fields displayed on the list page
  31. -------------------------------------------------
  32. You can customize the columns displayed on the list through the ``configureListFields`` method.
  33. Here is an example:
  34. .. code-block:: php
  35. <?php
  36. // ...
  37. public function configureListFields(ListMapper $listMapper)
  38. {
  39. $listMapper
  40. // addIdentifier allows to specify that this column
  41. // will provide a link to the entity
  42. // (edit or show route, depends on your access rights)
  43. ->addIdentifier('name')
  44. // you may specify the field type directly as the
  45. // second argument instead of in the options
  46. ->add('isVariation', 'boolean')
  47. // if null, the type will be guessed
  48. ->add('enabled', null, array(
  49. 'editable' => true
  50. ))
  51. // editable association field
  52. ->add('status', 'choice', array(
  53. 'editable' => true,
  54. 'class' => 'Vendor\ExampleBundle\Entity\ExampleStatus',
  55. 'choices' => array(
  56. 1 => 'Active',
  57. 2 => 'Inactive',
  58. 3 => 'Draft',
  59. ),
  60. ))
  61. // we can add options to the field depending on the type
  62. ->add('price', 'currency', array(
  63. 'currency' => $this->currencyDetector->getCurrency()->getLabel()
  64. ))
  65. // Here we specify which property is used to render the label of each entity in the list
  66. ->add('productCategories', null, array(
  67. 'associated_property' => 'name')
  68. )
  69. // you may also use dotted-notation to access
  70. // specific properties of a relation to the entity
  71. ->add('image.name')
  72. // You may also specify the actions you want to be displayed in the list
  73. ->add('_action', null, array(
  74. 'actions' => array(
  75. 'show' => array(),
  76. 'edit' => array(),
  77. 'delete' => array(),
  78. )
  79. ))
  80. ;
  81. }
  82. Options
  83. ^^^^^^^
  84. .. note::
  85. * ``(m)`` stands for mandatory
  86. * ``(o)`` stands for optional
  87. - ``type`` (m): defines the field type - mandatory for the field description itself but will try to detect the type automatically if not specified
  88. - ``template`` (o): the template used to render the field
  89. - ``label`` (o): the name used for the column's title
  90. - ``link_parameters`` (o): add link parameter to the related Admin class when the ``Admin::generateUrl`` is called
  91. - ``code`` (o): the method name to retrieve the related value (for example,
  92. if you have an `array` type field, you would like to show info prettier
  93. than `[0] => 'Value'`; useful when simple getter is not enough).
  94. Notice: works with string-like types (string, text, html)
  95. - ``associated_property`` (o): property path to retrieve the "string" representation of the collection element, or a closure with the element as argument and return a string.
  96. - ``identifier`` (o): if set to true a link appears on the value to edit the element
  97. Available types and associated options
  98. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  99. .. note::
  100. ``(m)`` means that option is mandatory
  101. +-----------+----------------+-----------------------------------------------------------------------+
  102. | Type | Options | Description |
  103. +===========+================+=======================================================================+
  104. | actions | actions | List of available actions |
  105. +-----------+----------------+-----------------------------------------------------------------------+
  106. | batch | | Renders a checkbox |
  107. +-----------+----------------+-----------------------------------------------------------------------+
  108. | select | | Renders a select box |
  109. +-----------+----------------+-----------------------------------------------------------------------+
  110. | array | | Displays an array |
  111. +-----------+----------------+-----------------------------------------------------------------------+
  112. | boolean | ajax_hidden | Yes/No; ajax_hidden allows to hide list field during an AJAX context. |
  113. +-----------+----------------+-----------------------------------------------------------------------+
  114. | boolean | editable | Yes/No; editable allows to edit directly from the list if authorized. |
  115. +-----------+----------------+-----------------------------------------------------------------------+
  116. | choice | choices | Possible choices |
  117. + +----------------+-----------------------------------------------------------------------+
  118. | | multiple | Is it a multiple choice option? Defaults to false. |
  119. + +----------------+-----------------------------------------------------------------------+
  120. | | delimiter | Separator of values if multiple. |
  121. + +----------------+-----------------------------------------------------------------------+
  122. | | catalogue | Translation catalogue. |
  123. + +----------------+-----------------------------------------------------------------------+
  124. | | class | Class path for editable association field. |
  125. +-----------+----------------+-----------------------------------------------------------------------+
  126. | currency | currency (m) | A currency string (EUR or USD for instance). |
  127. +-----------+----------------+-----------------------------------------------------------------------+
  128. | date | format | A format understandable by Twig's ``date`` function. |
  129. +-----------+----------------+-----------------------------------------------------------------------+
  130. | datetime | format | A format understandable by Twig's ``date`` function. |
  131. +-----------+----------------+-----------------------------------------------------------------------+
  132. | email | as_string | Renders the email as string, without any link. |
  133. + +----------------+-----------------------------------------------------------------------+
  134. | | subject | Add subject parameter to email link. |
  135. + +----------------+-----------------------------------------------------------------------+
  136. | | body | Add body parameter to email link. |
  137. +-----------+----------------+-----------------------------------------------------------------------+
  138. | percent | | Renders value as a percentage. |
  139. +-----------+----------------+-----------------------------------------------------------------------+
  140. | string | | Renders a simple string. |
  141. +-----------+----------------+-----------------------------------------------------------------------+
  142. | text | | See 'string' |
  143. +-----------+----------------+-----------------------------------------------------------------------+
  144. | html | | Renders string as html |
  145. +-----------+----------------+-----------------------------------------------------------------------+
  146. | time | | Renders a datetime's time with format ``H:i:s``. |
  147. +-----------+----------------+-----------------------------------------------------------------------+
  148. | trans | catalogue | Translates the value with catalogue ``catalogue`` if defined. |
  149. +-----------+----------------+-----------------------------------------------------------------------+
  150. | url | url | Adds a link with url ``url`` to the displayed value |
  151. + +----------------+-----------------------------------------------------------------------+
  152. | | route | Give a route to generate the url |
  153. + + + +
  154. | | name | Route name |
  155. + + + +
  156. | | parameters | Route parameters |
  157. + +----------------+-----------------------------------------------------------------------+
  158. | | hide_protocol | Hide http:// or https:// (default: false) |
  159. +-----------+----------------+-----------------------------------------------------------------------+
  160. If you have the SonataDoctrineORMAdminBundle installed, you have access to more field types, see `SonataDoctrineORMAdminBundle Documentation <https://sonata-project.org/bundles/doctrine-orm-admin/master/doc/reference/list_field_definition.html>`_.
  161. Customizing the query used to generate the list
  162. -----------------------------------------------
  163. You can customize the list query thanks to the ``createQuery`` method.
  164. .. code-block:: php
  165. <?php
  166. public function createQuery($context = 'list')
  167. {
  168. $query = parent::createQuery($context);
  169. $query->andWhere(
  170. $query->expr()->eq($query->getRootAliases()[0] . '.my_field', ':my_param')
  171. );
  172. $query->setParameter('my_param', 'my_value');
  173. return $query;
  174. }
  175. Customizing the sort order
  176. --------------------------
  177. Configure the default ordering in the list view
  178. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  179. Configuring the default ordering column can simply be achieved by overriding
  180. the ``datagridValues`` array property. All three keys ``_page``, ``_sort_order`` and
  181. ``_sort_by`` can be omitted.
  182. .. code-block:: php
  183. <?php
  184. // src/AppBundle/Admin/PostAdmin.php
  185. use Sonata\AdminBundle\Admin\AbstractAdmin;
  186. class PostAdmin extends AbstractAdmin
  187. {
  188. // ...
  189. protected $datagridValues = array(
  190. // display the first page (default = 1)
  191. '_page' => 1,
  192. // reverse order (default = 'ASC')
  193. '_sort_order' => 'DESC',
  194. // name of the ordered field (default = the model's id field, if any)
  195. '_sort_by' => 'updatedAt',
  196. );
  197. // ...
  198. }
  199. .. note::
  200. The ``_sort_by`` key can be of the form ``mySubModel.mySubSubModel.myField``.
  201. .. note::
  202. **TODO**: how to sort by multiple fields (this might be a separate recipe?)
  203. Filters
  204. -------
  205. You can add filters to let user control which data will be displayed.
  206. .. code-block:: php
  207. <?php
  208. // src/AppBundle/Admin/PostAdmin.php
  209. use Sonata\AdminBundle\Datagrid\DatagridMapper;
  210. class ClientAdmin extends AbstractAdmin
  211. {
  212. protected function configureDatagridFilters(DatagridMapper $datagridMapper)
  213. {
  214. $datagridMapper
  215. ->add('phone')
  216. ->add('email')
  217. ;
  218. }
  219. // ...
  220. }
  221. All filters are hidden by default for space-saving. User has to check which filter he wants to use.
  222. To make the filter always visible (even when it is inactive), set the parameter
  223. ``show_filter`` to ``true``.
  224. .. code-block:: php
  225. <?php
  226. protected function configureDatagridFilters(DatagridMapper $datagridMapper)
  227. {
  228. $datagridMapper
  229. ->add('phone')
  230. ->add('email', null, array(
  231. 'show_filter' => true
  232. ))
  233. // ...
  234. ;
  235. }
  236. By default the template generates an ``operator`` for a filter which defaults to ``sonata_type_equal``.
  237. Though this ``operator_type`` is automatically detected it can be changed or even be hidden:
  238. .. code-block:: php
  239. protected function configureDatagridFilters(DatagridMapper $datagridMapper)
  240. {
  241. $datagridMapper
  242. ->add('foo', null, array(
  243. 'operator_type' => 'sonata_type_boolean'
  244. ))
  245. ->add('bar', null, array(
  246. 'operator_type' => 'hidden'
  247. ))
  248. // ...
  249. ;
  250. }
  251. If you don't need the advanced filters, or all your ``operator_type`` are hidden, you can disable them by setting
  252. ``advanced_filter`` to ``false``. You need to disable all advanced filters to make the button disappear.
  253. .. code-block:: php
  254. protected function configureDatagridFilters(DatagridMapper $datagridMapper)
  255. {
  256. $datagridMapper
  257. ->add('bar', null, array(
  258. 'operator_type' => 'hidden',
  259. 'advanced_filter' => false
  260. ))
  261. // ...
  262. ;
  263. }
  264. Default filters
  265. ^^^^^^^^^^^^^^^
  266. Default filters can be added to the datagrid values by using the ``configureDefaultFilterValues`` method.
  267. A filter has a ``value`` and an optional ``type``. If no ``type`` is given the default type ``is equal`` is used.
  268. .. code-block:: php
  269. public function configureDefaultFilterValues(array &$filterValues)
  270. {
  271. $filterValues['foo'] = array(
  272. 'type' => ChoiceFilter::TYPE_CONTAINS,
  273. 'value' => 'bar',
  274. );
  275. }
  276. Available types are represented through classes which can be found here:
  277. https://github.com/sonata-project/SonataCoreBundle/tree/master/Form/Type
  278. Types like ``equal`` and ``boolean`` use constants to assign a choice of ``type`` to an ``integer`` for its ``value``:
  279. .. code-block:: php
  280. <?php
  281. // SonataCoreBundle/Form/Type/EqualType.php
  282. namespace Sonata\CoreBundle\Form\Type;
  283. class EqualType extends AbstractType
  284. {
  285. const TYPE_IS_EQUAL = 1;
  286. const TYPE_IS_NOT_EQUAL = 2;
  287. }
  288. The integers are then passed in the URL of the list action e.g.:
  289. **/admin/user/user/list?filter[enabled][type]=1&filter[enabled][value]=1**
  290. This is an example using these constants for an ``boolean`` type:
  291. .. code-block:: php
  292. use Sonata\UserBundle\Admin\Model\UserAdmin as SonataUserAdmin;
  293. use Sonata\CoreBundle\Form\Type\EqualType;
  294. use Sonata\CoreBundle\Form\Type\BooleanType;
  295. class UserAdmin extends SonataUserAdmin
  296. {
  297. protected $datagridValues = array(
  298. 'enabled' => array(
  299. 'type' => EqualType::TYPE_IS_EQUAL, // => 1
  300. 'value' => BooleanType::TYPE_YES // => 1
  301. )
  302. );
  303. }
  304. Please note that setting a ``false`` value on a the ``boolean`` type will not work since the type expects an integer of ``2`` as ``value`` as defined in the class constants:
  305. .. code-block:: php
  306. <?php
  307. // SonataCoreBundle/Form/Type/BooleanType.php
  308. namespace Sonata\CoreBundle\Form\Type;
  309. class BooleanType extends AbstractType
  310. {
  311. const TYPE_YES = 1;
  312. const TYPE_NO = 2;
  313. }
  314. Default filters can also be added to the datagrid values by overriding the ``getFilterParameters`` method.
  315. .. code-block:: php
  316. use Sonata\CoreBundle\Form\Type\EqualType;
  317. use Sonata\CoreBundle\Form\Type\BooleanType;
  318. class UserAdmin extends SonataUserAdmin
  319. {
  320. public function getFilterParameters()
  321. {
  322. $this->datagridValues = array_merge(array(
  323. 'enabled' => array (
  324. 'type' => EqualType::TYPE_IS_EQUAL,
  325. 'value' => BooleanType::TYPE_YES
  326. )
  327. ), $this->datagridValues);
  328. return parent::getFilterParameters();
  329. }
  330. }
  331. This approach is useful when you need to create dynamic filters.
  332. .. code-block:: php
  333. class PostAdmin extends SonataUserAdmin
  334. {
  335. public function getFilterParameters()
  336. {
  337. // Assuming security context injected
  338. if (!$this->securityContext->isGranted('ROLE_ADMIN')) {
  339. $user = $this->securityContext->getToken()->getUser();
  340. $this->datagridValues = array_merge(array(
  341. 'author' => array (
  342. 'type' => EqualType::TYPE_IS_EQUAL,
  343. 'value' => $user->getId()
  344. )
  345. ), $this->datagridValues);
  346. }
  347. return parent::getFilterParameters();
  348. }
  349. }
  350. Please note that this is not a secure approach to hide posts from others. It's just an example for setting filters on demand.
  351. Callback filter
  352. ^^^^^^^^^^^^^^^
  353. If you have the **SonataDoctrineORMAdminBundle** installed you can use the ``doctrine_orm_callback`` filter type e.g. for creating a full text filter:
  354. .. code-block:: php
  355. use Sonata\UserBundle\Admin\Model\UserAdmin as SonataUserAdmin;
  356. use Sonata\AdminBundle\Datagrid\DatagridMapper;
  357. class UserAdmin extends SonataUserAdmin
  358. {
  359. protected function configureDatagridFilters(DatagridMapper $datagridMapper)
  360. {
  361. $datagridMapper
  362. ->add('full_text', CallbackFilter::class, array(
  363. 'callback' => array($this, 'getFullTextFilter'),
  364. 'field_type' => 'text'
  365. ))
  366. // ...
  367. ;
  368. }
  369. public function getFullTextFilter($queryBuilder, $alias, $field, $value)
  370. {
  371. if (!$value['value']) {
  372. return;
  373. }
  374. // Use `andWhere` instead of `where` to prevent overriding existing `where` conditions
  375. $queryBuilder->andWhere($queryBuilder->expr()->orX(
  376. $queryBuilder->expr()->like($alias.'.username', $queryBuilder->expr()->literal('%' . $value['value'] . '%')),
  377. $queryBuilder->expr()->like($alias.'.firstName', $queryBuilder->expr()->literal('%' . $value['value'] . '%')),
  378. $queryBuilder->expr()->like($alias.'.lastName', $queryBuilder->expr()->literal('%' . $value['value'] . '%'))
  379. ));
  380. return true;
  381. }
  382. }
  383. You can also get the filter type which can be helpful to change the operator type of your condition(s):
  384. .. code-block:: php
  385. use Sonata\CoreBundle\Form\Type\EqualType;
  386. class UserAdmin extends SonataUserAdmin
  387. {
  388. public function getFullTextFilter($queryBuilder, $alias, $field, $value)
  389. {
  390. if (!$value['value']) {
  391. return;
  392. }
  393. $operator = $value['type'] == EqualType::TYPE_IS_EQUAL ? '=' : '!=';
  394. $queryBuilder
  395. ->andWhere($alias.'.username '.$operator.' :username')
  396. ->setParameter('username', $value['value'])
  397. ;
  398. return true;
  399. }
  400. }
  401. .. note::
  402. **TODO**:
  403. * basic filter configuration and options
  404. * targeting submodel fields using dot-separated notation
  405. * advanced filter options (global_search)
  406. Visual configuration
  407. --------------------
  408. You have the possibility to configure your List View to customize the render without overriding to whole template.
  409. You can :
  410. - `header_style`: Customize the style of header (width, color, background, align...)
  411. - `header_class`: Customize the class of the header
  412. - `collapse`: Allow to collapse long text fields with a "read more" link
  413. - `row_align`: Customize the alignment of the rendered inner cells
  414. - `label_icon`: Add an icon before label
  415. .. code-block:: php
  416. <?php
  417. public function configureListFields(ListMapper $list)
  418. {
  419. $list
  420. ->add('id', null, array(
  421. 'header_style' => 'width: 5%; text-align: center',
  422. 'row_align' => 'center'
  423. ))
  424. ->add('name', 'text', array(
  425. 'header_style' => 'width: 35%'
  426. )
  427. ->add('description', 'text', array(
  428. 'header_style' => 'width: 35%',
  429. 'collapse' => true
  430. )
  431. ->add('upvotes', null, array(
  432. 'label_icon' => 'fa fa-thumbs-o-up'
  433. )
  434. ->add('actions', null, array(
  435. 'header_class' => 'customActions',
  436. 'row_align' => 'right'
  437. )
  438. // ...
  439. ;
  440. }
  441. If you want to customise the `collapse` option, you can also give an array to override the default parameters.
  442. .. code-block:: php
  443. // ...
  444. ->add('description', 'text', array(
  445. 'header_style' => 'width: 35%',
  446. 'collapse' => array(
  447. 'height' => 40, // height in px
  448. 'read_more' => 'I want to see the full description', // content of the "read more" link
  449. 'read_less' => 'This text is too long, reduce the size' // content of the "read less" link
  450. )
  451. )
  452. // ...
  453. If you want to show only the `label_icon`:
  454. .. code-block:: php
  455. // ...
  456. ->add('upvotes', null, array(
  457. 'label' => false,
  458. 'label_icon' => 'fa fa-thumbs-o-up'
  459. )
  460. // ...
  461. .. _`issues on GitHub`: https://github.com/sonata-project/SonataAdminBundle/issues/1519
  462. Mosaic view button
  463. ------------------
  464. You have the possibility to show/hide mosaic view button.
  465. .. code-block:: yaml
  466. sonata_admin:
  467. # for hide mosaic view button on all screen using `false`
  468. show_mosaic_button: true
  469. You can show/hide mosaic view button using admin service configuration. You need to add option ``show_mosaic_button``
  470. in your admin services:
  471. .. code-block:: yaml
  472. sonata_admin.admin.post:
  473. class: Sonata\AdminBundle\Admin\PostAdmin
  474. arguments: [~, Sonata\AdminBundle\Entity\Post, ~]
  475. tags:
  476. - { name: sonata.admin, manager_type: orm, group: admin, label: Post, show_mosaic_button: true }
  477. sonata_admin.admin.news:
  478. class: Sonata\AdminBundle\Admin\NewsAdmin
  479. arguments: [~, Sonata\AdminBundle\Entity\News, ~]
  480. tags:
  481. - { name: sonata.admin, manager_type: orm, group: admin, label: News, show_mosaic_button: false }
  482. Checkbox range selection
  483. ------------------------
  484. .. tip::
  485. You can check / uncheck a range of checkboxes by clicking a first one,
  486. then a second one with shift + click.