EasyAdmin Collection Field ========================== This field displays a collection of objects, usually by rendering a list of embedded forms. In :ref:`form pages (edit and new) ` it looks like this: .. image:: ../images/fields/field-collection-simple.png :alt: Default style of EasyAdmin collection field When you click on any of the list items, its contents are expanded and you can access its embedded form: .. image:: ../images/fields/field-collection-simple-expanded.png :alt: Default style of EasyAdmin collection field expanded Basic Information ----------------- * **PHP Class**: ``EasyCorp\Bundle\EasyAdminBundle\Field\CollectionField`` * **Doctrine DBAL Type** used to store this value: this field is related to Doctrine associations, so indirectly it uses ``integer``, ``guid`` or any other type that you use to store the ID of the associated entity * **Symfony Form Type** used to render the field: `CollectionType`_ * **Rendered as**: .. code-block:: html Prerequisites ------------- As explained in the `documentation about Symfony CollectionType options`_, the ``allowAdd`` and ``allowDelete`` option requires that your entity defines some special methods with very specific names. Otherwise, changes won't be persisted when creating or updating the entity collection items in the backend. Consider a ``BlogPost`` entity that defines a one-to-many relation with a ``Comment`` entity and a many-to-many relation with a ``Tag`` entity:: use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; // ... class BlogPost { // ... #[ORM\OneToMany(targetEntity: Comment::class, mappedBy: 'post', orphanRemoval: true, cascade: ['persist'])] private Collection $comments; #[ORM\ManyToMany(targetEntity: Tag::class, cascade: ['persist'])] #[ORM\JoinTable(name: 'my_app_blogpost_tag')] private Collection $tags; } In order to add/delete comments or tags, you must define "adder" and "remover" methods called ``add()`` and ``remove()``:: class BlogPost { // ... public function addComment(Comment $comment): void { $comment->setBlogPost($this); if (!$this->comments->contains($comment)) { $this->comments->add($comment); } } public function removeComment(Comment $comment): void { $this->comments->removeElement($comment); } public function addTag(Tag ...$tags): void { foreach ($tags as $tag) { if (!$this->tags->contains($tag)) { $this->tags->add($tag); } } } public function removeTag(Tag $tag): void { $this->tags->removeElement($tag); } } Options ------- allowAdd ~~~~~~~~ By default, you can add new items to the collection. Use this option if you prefer to not allow that:: yield CollectionField::new('...')->allowAdd(false); allowDelete ~~~~~~~~~~~ By default, you can delete any of the items included in the collection. Use this option if you prefer to not allow that:: yield CollectionField::new('...')->allowDelete(false); renderExpanded ~~~~~~~~~~~~~~ By default, items in the collection are represented by a single line showing their ``__toString()`` value. Users need to click on each item to reveal its embedded form. Use this option if you prefer to render all items expanded on page load:: yield CollectionField::new('...')->renderExpanded(); setEntryIsComplex ~~~~~~~~~~~~~~~~~ Set this option if the embedded form of each collection item contains multiple fields:: yield CollectionField::new('...')->setEntryIsComplex(); EasyAdmin will try to do its best to display those fields correctly:: .. image:: ../images/fields/field-collection-complex-expanded.png :alt: Default style of EasyAdmin complex collection field expanded setEntryType ~~~~~~~~~~~~ The entries of the collection can be rendered either using a Symfony Form or an EasyAdmin CRUD Form. The ``setEntryType()`` method defines the Symfony form type used to render the form of each collection entry:: yield CollectionField::new('...')->setEntryType(SomeType::class); setEntryToStringMethod ~~~~~~~~~~~~~~~~~~~~~~ By default, items in the collection are represented by a single line showing their ``__toString()`` value. Use this option to define how to get the string representation of each collection entry:: // this calls the 'getFullName()' method in the entity yield CollectionField::new('...')->setEntryToStringMethod('getFullName'); // you can also pass a callable to generate the string yield CollectionField::new('...')->setEntryToStringMethod(fn (): string => '...'); // your callable receives the entity and the translator service as arguments yield CollectionField::new('...')->setEntryToStringMethod( fn (Category $value, TranslatorInterface $translator): string => $translator->trans($value->getDescription()) ); showEntryLabel ~~~~~~~~~~~~~~ By default, EasyAdmin hides the form label of each collection item (because it's an auto-increment integer number which doesn't look good most of the times). Use this option if you prefer to display that label:: yield CollectionField::new('...')->showEntryLabel(); useEntryCrudForm ~~~~~~~~~~~~~~~~ The entries of the collection can be rendered either using a Symfony Form or an EasyAdmin CRUD Form. The ``useEntryCrudForm()`` method defines the EasyAdmin CRUD form used to render the form of each collection entry:: yield CollectionField::new('...')->useEntryCrudForm(); By default, EasyAdmin finds the CRUD controller associated to the property automatically. If you need better control about which CRUD controller to use, pass the fully-qualified class name of the controller as the first argument:: yield CollectionField::new('...')->useEntryCrudForm(CategoryCrudController::class); // the other optional arguments are the CRUD page names to pass to the configureFields() // method when creating and editing entries respectively yield CollectionField::new('...')->useEntryCrudForm( CategoryCrudController::class, 'new_category_on_article_page', 'edit_category_on_article_page' ); .. note:: The ``useEntryCrudForm()`` method requires Symfony 6.1 or newer version. JavaScript Events ----------------- When an item is added to a collection field, a `CustomEvent`_ with the type ``'ea.collection.item-added'`` is dispatched. Similarly, when an item is removed, an `Event`_ with the type ``'ea.collection.item-removed'`` is dispatched. The ``'ea.collection.item-added'`` event contains information about the added item in the `detail property`_: .. code-block:: javascript document.addEventListener('ea.collection.item-added', (event) => { const {newElement} = event.detail console.debug(newElement, 'added to collection') }); document.addEventListener('ea.collection.item-removed', (event) => { // Do something with the event console.debug('item removed from collection') }); .. _`CollectionType`: https://symfony.com/doc/current/reference/forms/types/collection.html .. _`documentation about Symfony CollectionType options`: https://symfony.com/doc/current/reference/forms/types/collection.html#field-options .. _`CustomEvent`: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent .. _`Event`: https://developer.mozilla.org/en-US/docs/Web/API/Event/Event .. _`detail property`: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail