Getting started
Take authors and their books: Book::$author is a ManyToOne, and Author::$books its inverse OneToMany.
The target CRUD controller
The list is the book index, filtered on the author. The book CRUD controller needs a filter on author:
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
use EasyCorp\Bundle\EasyAdminBundle\Filter\EntityFilter;
final class BookCrudController extends AbstractCrudController
{
public function configureFilters(Filters $filters): Filters
{
return $filters->add(EntityFilter::new('author'));
}
}Everything else the list shows (its columns, page size, default sort and row actions) is the book index's own configuration.
The field
use Janalis\EasyAdminEmbeddedList\Field\EmbeddedListField;
final class AuthorCrudController extends AbstractCrudController
{
public function configureFields(string $pageName): iterable
{
yield TextField::new('name');
yield EmbeddedListField::new('books', 'Books');
}
}The field finds the book CRUD controller from the mapping's target entity and the filter from the mapping's other side (mappedBy or inversedBy). Edit an author: the form shows their books, paginated and sortable.
- A new author has no list: there is nothing to filter on yet.
- The field never writes the collection: saving the form leaves it as it is.
- An unlabelled field spans the whole row; a labelled one takes the configured columns (
col-md-7 col-xxl-6).
On index and detail pages
The field shows the size of the collection. Give it a relatedUrl custom option to link that number:
EmbeddedListField::new('books', 'Books')
->setCustomOption('relatedUrl', $this->urls->setController(BookCrudController::class)->generateUrl());The template is @EasyAdminEmbeddedList/crud/field/embedded_list.html.twig. Replace it for every field in Configuration, or for one field with setTemplatePath().