Search code examples
phpsymfonyeasyadmin3

How to display associated objects with links to their details page in Symfony 5 EasyAdmin 3?


I have two entities, Offer and Candidate, with a OneToMany relationship between them. The relevant code parts are the followings:

In Offer.php:

    /**
     * @ORM\OneToMany(targetEntity=Candidate::class, mappedBy="offer", orphanRemoval=true)
     */
    private $candidates;

    public function __construct()
    {
        $this->candidates = new ArrayCollection();
    }

In Candidate.php:

    /**
     * @ORM\ManyToOne(targetEntity=Offer::class, inversedBy="candidates")
     * @ORM\JoinColumn(nullable=false)
     */
    private $offer;

In OfferCrudController.php:

    public function configureFields(string $pageName): iterable
    {
        return [
            ArrayField::new('candidates', new TranslatableMessage('easyadmin.candidates'))
                ->onlyOnDetail(),
            AssociationField::new('candidates', new TranslatableMessage('easyadmin.candidates'))
                ->onlyOnIndex()
        ];
    }

In CandidateCrudController.php:

    public function configureFields(string $pageName): iterable
    {
        return [
            AssociationField::new('offer', new TranslatableMessage('easyadmin.candidate.offer'))
        ];
    }

My problem is that while in the case of Candidates EasyAdmin displays the Offer linked to its details page for each Candidate, for the Offers it displays only the non-clickable string representations of the Candidates, as the images show it:

clickable Offers

non-clickable Candidates

Is it possible to display the Candidates too with their appropriate links to their details page?


Solution

  • Yes, it's possible, but you should create a custom template for this. Let's say, you've created /templates/admin/field/offer/detail/candidates.html.twig. Then in OfferCrudController need to set created template for candidates field*:

    public function configureFields(string $pageName): iterable
    {
        // ...
        yield AssociationField::new('candidates', 'Candidates')->onlyOnDetail()
                ->setTemplatePath('admin/field/offer/detail/candidates.html.twig');
    }
    
    • example with generator, but it can be easily written as array item, like in your example (instead ArrayField). I just prefer to use generator in that case, because that's more convenient to configure.

    And in template just generate URL for each entity:

    # /templates/admin/field/offer/detail/candidates.html.twig
    {% if field.value is not empty %}
        {% for candidate in field.value %}
            {% set candidateDetailUrl = ea_url()
                .setController('App\\Controller\\Admin\\CandidateCrudController')
                .setAction(constant('EasyCorp\\Bundle\\EasyAdminBundle\\Config\\Action::DETAIL'))
                .setEntityId(candidate.id)
            %}
            <a href="{{ candidateDetailUrl }}" style="display: block">
                {{ candidate.name }}
            </a>
        {% endfor %}
    {% else %}
        No candidates
    {% endif %}