Easyadminbundle: Linking to entities on AssociationField with many-to-one relationships - working on updated template for AssociationField.html.twig

Created on 17 Sep 2020  路  6Comments  路  Source: EasyCorp/EasyAdminBundle

Short description of what this feature will allow to do:
For an entity that has a many-to-one relationship, it's common to want to see a list of entities that are related on, e.g. its detail page. I've been working on updating the template to allow this to happen. This is what I have so far - this is the template for the AssociationField - at the moment I'm just setting the template path for an association field in the crud controller. It assumes that a crud controller exists for the linked entities:

{# @var ea \EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext #}
{# @var field \EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto #}
{# @var entity \EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto #}
{% if 'toMany' == field.customOptions.get('associationType') %}
    {% if field.value|length > 0 %}
    <ul>
        {# element is an instance of whatever entity that this is a collection of #}
        {% for element in field.value %}
        <li>
            <a href="/admin?crudAction=detail&crudId={{ ea.crudControllers.findCrudIdByCrudFqcn(field.customOption('crudControllerFqcn'))}}&entityId={{ element.id }}">
                {{ element }} {# Relying on the __toString to return a sensible string for the element #}
            </a>
        </li>
        {%  endfor %}
    </ul>
    {% endif %}
{% else %}
    {% if field.customOptions.get('relatedUrl') is not null %}
        <a href="{{ field.customOptions.get('relatedUrl') }}">{{ field.formattedValue }}</a>
    {% else %}
        {{ field.formattedValue }}
    {% endif %}
{% endif %}

Example of how to use this feature
This could replace the AssociationField template. One question though, maybe there's a better way to build the link to the entity using an easy admin twig function?

Most helpful comment

maybe there's a better way to build the link to the entity using an easy admin twig function?

There actually is! ea_url() will return the CrudUrlBuilder for you to build urls in the twig template. Slap the below code into the above template inside the li for a cleaner and more stable url generation.

                    {%
                        set url = ea_url()
                            .setController(field.customOption('crudControllerFqcn'))
                            .setEntityId(element.id)
                            .generateUrl()
                    %}
                    <a href="{{ url }}">

All 6 comments

This is great, and should be the default behaviour of AssociationField when it's a ToMany relationship, as was the behaviour in version 2.0. Instead, the 3.0 behaviour is to just output the number of entities which are related: https://github.com/EasyCorp/EasyAdminBundle/blob/master/src/Field/Configurator/AssociationConfigurator.php#L122

One question though, maybe there's a better way to build the link to the entity using an easy admin twig function?

You're probably right, but I'm using your code as-is for now. One change is making a class in order to avoid having to do a setTemplatePath() each time:

$deals = AssociationField::new('deals')->setTemplatePath('bundles/EasyAdminBundle/default/field_association.html.twig');

Instead, I'm using a new MultipleAssociationField class (code follows) like so:

$deals = MultipleAssociationField::new('deals');
<?php

namespace App\Controller\Admin\Field;

use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;

class MultipleAssociationField
{
    public static function new(string $propertyName, ?string $label = null): AssociationField
    {
        $field = AssociationField::new($propertyName, $label);
        $field->setTemplatePath('bundles/EasyAdminBundle/default/field_multiple_association.html.twig');

        return $field;
    }
}

I've adjusted your twig template slightly, because if an entity does not have a CRUD controller created for it, I get this error:

Argument 1 passed to EasyCorp\Bundle\EasyAdminBundle\Registry\CrudControllerRegistry::findCrudIdByCrudFqcn() must be of the type string, null given

            {% if field.customOption('crudControllerFqcn') %}
                <a href="/admin?crudAction=detail&crudId={{ ea.crudControllers.findCrudIdByCrudFqcn(field.customOption('crudControllerFqcn'))}}&entityId={{ element.id }}">
                    {{ element }} {# Relying on the __toString to return a sensible string for the element #}
                </a>
            {% else %}
                {{ element }}
            {% endif %}

I'd actually done this, but forgot to report back!

{% if field.customOption('crudControllerFqcn') is not empty %}

In the custom field class, it could be modified such as ul or ol as well

maybe there's a better way to build the link to the entity using an easy admin twig function?

There actually is! ea_url() will return the CrudUrlBuilder for you to build urls in the twig template. Slap the below code into the above template inside the li for a cleaner and more stable url generation.

                    {%
                        set url = ea_url()
                            .setController(field.customOption('crudControllerFqcn'))
                            .setEntityId(element.id)
                            .generateUrl()
                    %}
                    <a href="{{ url }}">

What's about this? Will be updated the template or should be implemented by us?

I've ran into this exact issue, showing a number of entities instead of their data is a lazy approach and should be extended ;)

Was this page helpful?
0 / 5 - 0 ratings