the_form_view.rst 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. The Form View
  2. =============
  3. You've seen the absolute top of the iceberg in
  4. :doc:`the previous chapter <creating_an_admin>`. But there is a lot more to
  5. discover! In the coming chapters, you'll create an Admin class for the more
  6. complex ``BlogPost`` model. Meanwhile, you'll learn how to make things a bit
  7. more pretty.
  8. Bootstrapping the Admin Class
  9. -----------------------------
  10. The basic class definition will look the same as the ``CategoryAdmin``:
  11. .. code-block:: php
  12. // src/AppBundle/Admin/BlogPostAdmin.php
  13. namespace AppBundle\Admin;
  14. use Sonata\AdminBundle\Admin\Admin;
  15. use Sonata\AdminBundle\Datagrid\ListMapper;
  16. use Sonata\AdminBundle\Datagrid\DatagridMapper;
  17. use Sonata\AdminBundle\Form\FormMapper;
  18. class BlogPostAdmin extends Admin
  19. {
  20. protected function configureFormFields(FormMapper $formMapper)
  21. {
  22. // ... configure $formMapper
  23. }
  24. protected function configureDatagridFilters(DatagridMapper $datagridMapper)
  25. {
  26. // ... configure $datagridMapper
  27. }
  28. protected function configureListFields(ListMapper $listMapper)
  29. {
  30. // ... configure $listMapper
  31. }
  32. }
  33. The same applies to the service definition:
  34. .. code-block:: yaml
  35. # app/config/services.yml
  36. # ...
  37. services:
  38. # ...
  39. admin.blog_post:
  40. class: AppBundle\Admin\BlogPostAdmin
  41. arguments: [~, AppBundle\Entity\BlogPost, ~]
  42. tags:
  43. - { name: sonata.admin, manager_type: orm, label: Blog post }
  44. Configuring the Form Mapper
  45. ---------------------------
  46. If you already know the `Symfony Form component`_, the ``FormMapper`` will look
  47. very similair.
  48. You use the ``add()`` method to add fields to the form. The first argument is
  49. the name of the property the field value maps to, the second argument is the
  50. type of the field (see the `field type reference`_) and the third argument are
  51. additional options to customize the form type. Only the first argument is
  52. required as the Form component has type guessers to guess the type.
  53. The ``BlogPost`` model has 4 properties: ``id``, ``title``, ``body``,
  54. ``category``. The ``id`` property's value is generated automatically by the
  55. database. This means the form view just needs 3 fields: title, body and
  56. category.
  57. The title and body fields are simple "text" and "textarea" fields, you can add
  58. them straight away:
  59. .. code-block:: php
  60. // src/AppBundle/Admin/BlogPostAdmin.php
  61. // ...
  62. protected function configureFormFields(FormMapper $formMapper)
  63. {
  64. $formMapper
  65. ->add('title', 'text')
  66. ->add('body', 'textarea')
  67. ;
  68. }
  69. However, the category field will reference another model. How can you solve that?
  70. Adding Fields that Reference Other Models
  71. -----------------------------------------
  72. You have a couple different choices on how to add fields that reference other
  73. models. The most basic choice is to use the `entity field type`_ provided by
  74. the DoctrineBundle. This will render a choice field with the available entities
  75. as choice.
  76. .. code-block:: php
  77. // src/AppBundle/Admin/BlogPostAdmin.php
  78. // ...
  79. protected function configureFormFields(FormMapper $formMapper)
  80. {
  81. $formMapper
  82. // ...
  83. ->add('category', 'entity', array(
  84. 'class' => 'AppBundle\Entity\Category',
  85. 'property' => 'name',
  86. ))
  87. ;
  88. }
  89. As each blog post will only have one category, it renders as a select list:
  90. .. image:: ../images/getting_started_entity_type.png
  91. When an admin would like to create a new category, they need to go to the
  92. category admin page and create a new category.
  93. Using the Sonata Model Type
  94. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  95. To make life easier for admins, you can use the
  96. :ref:`sonata_type_model field type <field-types-model>`. This field type will
  97. also render as a choice field, but it includes a create button to open an
  98. dialog with the admin of the referenced model in it:
  99. .. code-block:: php
  100. // src/AppBundle/Admin/BlogPostAdmin.php
  101. // ...
  102. protected function configureFormFields(FormMapper $formMapper)
  103. {
  104. $formMapper
  105. // ...
  106. ->add('category', 'sonata_type_model', array(
  107. 'class' => 'AppBundle\Entity\Category',
  108. 'property' => 'name',
  109. ))
  110. ;
  111. }
  112. .. image:: ../images/getting_started_sonata_model_type.png
  113. Using Groups
  114. ------------
  115. Currently, everything is put into one block. Since the form only has three
  116. fields, it is still usable, but it can become quite a mess pretty quick. To
  117. solve this, the form mapper also supports grouping fields together.
  118. For instance, the title and body fields can belong to the Content group and the
  119. category field to a Meta data group. To do this, use the ``with()`` method:
  120. .. code-block:: php
  121. // src/AppBundle/Admin/BlogPostAdmin.php
  122. // ...
  123. protected function configureFormFields(FormMapper $formMapper)
  124. {
  125. $formMapper
  126. ->with('Content')
  127. ->add('title', 'text')
  128. ->add('body', 'textarea')
  129. ->end()
  130. ->with('Meta data')
  131. ->add('category', 'sonata_type_model', array(
  132. 'class' => 'AppBundle\Entity\Category',
  133. 'property' => 'name',
  134. ))
  135. ->end()
  136. ;
  137. }
  138. The first argument is the name/label of the group and the second argument is an
  139. array of options. For instance, you can pass HTML classes to the group in
  140. order to tweak the styling:
  141. .. code-block:: php
  142. // src/AppBundle/Admin/BlogPostAdmin.php
  143. // ...
  144. protected function configureFormFields(FormMapper $formMapper)
  145. {
  146. $formMapper
  147. ->with('Content', array('class' => 'col-md-9'))
  148. // ...
  149. ->end()
  150. ->with('Meta data', array('class' => 'col-md-3')
  151. // ...
  152. ->end()
  153. ;
  154. }
  155. This will now result in a much nicer edit page:
  156. .. image:: getting_started_post_edit_grid.png
  157. Using Tabs
  158. ~~~~~~~~~~
  159. If you get even more options, you can also use multiple tabs by using the
  160. ``tab()`` shortcut method:
  161. .. code-block:: php
  162. $formMapper
  163. ->tab('Post')
  164. ->group('Content', ...)
  165. // ...
  166. ->end()
  167. // ...
  168. ->end()
  169. ->tab('Publish Options')
  170. // ...
  171. ->end()
  172. ;
  173. Creating a Blog Post
  174. --------------------
  175. You've now finished your nice form view for the ``BlogPost`` model. Now it's
  176. time to test it out by creating a post.
  177. After pressing the "Create" button, you probably see a green message like:
  178. *Item "AppBundle\Entity\BlogPost:00000000192ba93c000000001b786396" has been
  179. successfully created.*
  180. While it's very friendly of the SonataAdminBundle to notify the admin of a
  181. succesful creation, the classname and some sort of hash aren't really nice to
  182. read. This is the default string representation of an object in the
  183. SonataAdminBundle. You can change it by defining a ``__toString()`` magic
  184. method on your model or by defining a ``toString()`` (note: no underscore
  185. prefix) method in the Admin class. This recieves the object to transform to a
  186. string as the first parameter:
  187. .. code-block:: php
  188. // src/AppBundle/Admin/BlogPostAdmin.php
  189. // ...
  190. use AppBundle\Entity\BlogPost;
  191. class BlogPostAdmin extends Admin
  192. {
  193. // ...
  194. public function toString($object)
  195. {
  196. return $object instanceof BlogPost
  197. ? $object->getTitle()
  198. : 'Blog Post'; // shown in the breadcrumb on the create view
  199. }
  200. }
  201. Round Up
  202. --------
  203. In this tutorial, you've made your first contact with the greatest feature of
  204. the SonataAdminBundle: Being able to customize literally everything. You've
  205. started by creating a simple form and ended up with a nice edit page for your
  206. admin.
  207. In the :doc:`next chapter <>`, you're going to look at the list and datagrid
  208. actions.
  209. .. _`Symfony Form component`: http://symfony.com/doc/current/book/forms.html
  210. .. _`field type reference`: http://symfony.com/doc/current/reference/forms/types.html
  211. .. _`entity field type`: http://symfony.com/doc/current/reference/forms/types/entity.html