Easyadminbundle: Sort Choice

Created on 9 Feb 2016  路  13Comments  路  Source: EasyCorp/EasyAdminBundle

Hi

I have a form, in one field I have a choice type (city) from a foreign entity, is there a way to show the options on the select sorted? y try this "params: { sortField: 'cityName'} " this is my config.

DeparturePoint:
            label: 'Puntos de salida'
            class: MB2\ATRBundle\Entity\DeparturePoint
            search:
              fields: ['name']
            list:
                title: "Puntos de salida"
                fields:
                    - 'id'
                    - { property: 'name', label: 'Nombre' }
                    - { property: 'code', label: 'C贸digo' }
                    - { property: 'oaciCode', label: 'C贸digo OACI' }
                    - { property: 'transportationType', label: 'Tipo de transporte' }
                    - { property: 'city', label: 'Ciudad' }
                    - { property: 'active', type: 'boolean', label: 'Activo' }
                    - { property: 'createdBy', label: 'Creado por' }
            form:
                title: "Puntos de salida"
                fields:
                    - { property: 'name', label: 'Nombre' }
                    - { property: 'code', label: 'C贸digo' }
                    - { property: 'oaciCode', label: 'C贸digo OACI' }
                    - { property: 'transportationType', label: 'Tipo de transporte' }
                    - { property: 'city', label: 'Ciudad', params: { sortField: 'cityName'}  }
                    - { property: 'active', label: 'Activo' }`

Thanks

Most helpful comment

Here is how I fixed it, in case it helps somebody. I am not sure whether this is the best way around or not, but it works for me :)

My issue

In my case, just to reply to @javiereguiluz 's post from Feb 16, I could not use the @OrderBy annotation because it seems to be only available for OneToMany and ManyToMany associations.

I have an Event class with the $type field : one event is related to 1..1 type, one type to 0..N events.

file: src/Entity/Event.php

class Event
{
...
    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\EventType")
     * @ORM\JoinColumn(nullable=false)
     * @Assert\NotNull
     */
    private $type;
...

When I display the form view for the Event class, I do have a dropdown list for all EventType entities, with sorting based on the EventType ID... whereas I need sorting based on the label.

Solution

I had to override AdminController for my entity:

file: src/config/packages/easy_admin.yaml

easy_admin:
    entities:
        Event:
            controller: App\Controller\EasyAdmin\EventController

Create a custom QueryBuilder in it :

file: src/Controller/EasyAdmin/EventController.php

use EasyCorp\Bundle\EasyAdminBundle\Controller\AdminController;

class EventController extends AdminController
{
    public function getEventTypeQueryBuilder(EntityRepository $er)
    {
        return $er->createQueryBuilder('event_type')->orderBy('event_type.label', 'ASC');
    }
}

And ask for the use of the custom query builder in the config file:

file: src/config/packages/easy_admin.yaml

easy_admin:
    entities:
        Event:
            form:
                fields:
                    -
                        property: type
                        type_options:
                            query_builder: [App\Controller\EasyAdmin\EventController, getEventTypeQueryBuilder]

What do you think?

I was almost certain that there was some kind of class-level annotation, provided by Doctrine, which allowed to define the default "order by" directive applied to the related entity for all subsequent requests. I was not able to find it though. I could not make it work with anything less verbose as well.

If someone has an easier solution for that, please let us know!

All 13 comments

If we are talking about a form, then this has to be solved via the Symfony Form component options. I don't know which option controls this, but from EasyAdmin point of view, you must use the type_options option:

DeparturePoint:
    form:
        fields:
            - { property: 'city', label: 'Ciudad', type_options: { ... }  }

Thank you Javier

How can I use the type_options to sort the choice element? Or I have to create a form and sort it from there?

@gastoncs Where do the elements of your choice come from? Can't you just use PHP's *sort functions?

@Pierstoval I don't have any form, I just setup the config (see above) and the bundle build it by itself, this is the DeparturePoint entity where I have the relationship. please look at the city property.

class DeparturePoint
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=150, nullable=false)
     */
    private $name;

    /**
     * @ORM\Column(type="string", length=5, nullable=true)
     * @Assert\NotBlank(message = "not_blank")
     * @Assert\Regex(
     *      pattern= "/^([^0-9]*)$/",
     *      message="No se permiten n煤meros"
     * )
     * @Assert\Length(
     *      min = "3",
     *      max = "3",
     *      minMessage = "M铆nimo {{ limit }} caracteres",
     *      maxMessage = "M谩ximo {{ limit }} caracteres"
     * )
     */
    private $code;

    /**
     * @ORM\Column(type="string", length=4, nullable=true)
     * @Assert\Regex(
     *      pattern= "/^([^0-9]*)$/",
     *      message="No se permiten n煤meros"
     * )
     * @Assert\Length(
     *      min = "4",
     *      max = "4",
     *      minMessage = "M铆nimo {{ limit }} caracteres",
     *      maxMessage = "M谩ximo {{ limit }} caracteres"
     * )
     */
    private $oaciCode;

    /**
     * @ORM\ManyToOne(targetEntity="MB2\ATRBundle\Entity\TransportationType")
     * @ORM\JoinColumn(name="trasp_type_id", referencedColumnName="id", nullable=false)
     */
    private $transportationType;

    /**
     * @ORM\ManyToOne(targetEntity="MB2\ATRBundle\Entity\City")
     * @ORM\JoinColumn(name="city_id", referencedColumnName="id", nullable=true)
     */
    private $city;

    /**
     * @ORM\Column(type="datetime", nullable=false)
     *
     */
    private $created;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    private $updated;

    /**
     * @ORM\ManyToOne(targetEntity="MB2\ATRBundle\Entity\MBUser")
     * @ORM\JoinColumn(name="created_by", referencedColumnName="id", nullable=false)
     *
     */
    private $createdBy;

    /**
     * @ORM\ManyToOne(targetEntity="MB2\ATRBundle\Entity\MBUser")
     * @ORM\JoinColumn(name="updated_by", referencedColumnName="id")
     */
    private $updatedBy;

    /**
     * @ORM\Column(type="boolean", nullable=false, options={"default":true})
     */
    private $active=true;

The thing is that it just dump the table data sorted by the id, I will like to sort it by the name.

Maybe I will have to create a form (DeparturepontType()) and do the sort there.

Ok, so this choice is bound to an entity, this is what I wanted to know actually.

For what you want, you should create a createDeparturePointEntityFormBuilder method in your own AdminController and add something similar to this:

/**
 * @see AdminController::createEntityFormBuilder
 */
public function createDeparturePointEntityFormBuilder($entity, $view)
{
    $builder = parent::createEntityFormBuilder($entity, $view);

    $cityBuilder = $builder->get('city');
    $cityType = get_class($cityBuilder->getType());
    $cityOptions = $cityBuilder->getOptions();

    $cityOptions['query_builder'] = function (EntityRepository $er) {
        return $er->createQueryBuilder('city')
            ->orderBy('city.name', 'ASC');
    };

    $builder->add('city', $cityType, $cityOptions);

    return $builder;
}

This should work, I guess.

The goal here is to overwrite the city form field but keeping its resolved options, so we get them all, and re-add it. Symfony Form component will automatically erase the previous and add the new form field so it is identical to the previous, minus the query_builder option you added that specifies how to retrieve the entities in the relationship.

@Pierstoval I have the older version 1.5.5, I should upgrade it first, I feel concern that something might come up wrong.

Thank you!

@Pierstoval I am getting this error

Could not load type "SymfonyComponent\Form\Extension\DataCollector\Proxy\ResolvedTypeDataCollectorProxy"

do you know why?

Thanks

@gastoncs can't you just use the @OrderBy({"name" = "ASC"}) annotation provided by Doctrine? See http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/tutorials/ordered-associations.html

did you find the solution ? i have the same problem :(
adding the annotation @OrderBy provided by doctrine didn't make a change.

Here is how I fixed it, in case it helps somebody. I am not sure whether this is the best way around or not, but it works for me :)

My issue

In my case, just to reply to @javiereguiluz 's post from Feb 16, I could not use the @OrderBy annotation because it seems to be only available for OneToMany and ManyToMany associations.

I have an Event class with the $type field : one event is related to 1..1 type, one type to 0..N events.

file: src/Entity/Event.php

class Event
{
...
    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\EventType")
     * @ORM\JoinColumn(nullable=false)
     * @Assert\NotNull
     */
    private $type;
...

When I display the form view for the Event class, I do have a dropdown list for all EventType entities, with sorting based on the EventType ID... whereas I need sorting based on the label.

Solution

I had to override AdminController for my entity:

file: src/config/packages/easy_admin.yaml

easy_admin:
    entities:
        Event:
            controller: App\Controller\EasyAdmin\EventController

Create a custom QueryBuilder in it :

file: src/Controller/EasyAdmin/EventController.php

use EasyCorp\Bundle\EasyAdminBundle\Controller\AdminController;

class EventController extends AdminController
{
    public function getEventTypeQueryBuilder(EntityRepository $er)
    {
        return $er->createQueryBuilder('event_type')->orderBy('event_type.label', 'ASC');
    }
}

And ask for the use of the custom query builder in the config file:

file: src/config/packages/easy_admin.yaml

easy_admin:
    entities:
        Event:
            form:
                fields:
                    -
                        property: type
                        type_options:
                            query_builder: [App\Controller\EasyAdmin\EventController, getEventTypeQueryBuilder]

What do you think?

I was almost certain that there was some kind of class-level annotation, provided by Doctrine, which allowed to define the default "order by" directive applied to the related entity for all subsequent requests. I was not able to find it though. I could not make it work with anything less verbose as well.

If someone has an easier solution for that, please let us know!

Some improvement on the solution above: The first code block is not necessary:

controller: App\Controller\EasyAdmin\EventController

It works (thanks !) but I have this warning :
Deprecated: Non-static method App\Controller\EasyAdmin\BetPatternController::getSportQueryBuilder() should not be called statically

Thank you so much elietheocari. I was also able to get this solution to work.

I had to make one change: I was not able to put my custom controller in src/Controller/EasyAdmin. This gave me a "Name Already In Use" error. I had to simply put it in src/Controller/.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

BigMichi1 picture BigMichi1  路  3Comments

joazvsoares picture joazvsoares  路  4Comments

lukasluecke picture lukasluecke  路  3Comments

ziobudda picture ziobudda  路  4Comments

haithem-rihane picture haithem-rihane  路  4Comments