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

Issue

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 %}

Answered By – yaroslavche

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published