Easyadminbundle: Choice form field values

Created on 18 Aug 2015  路  6Comments  路  Source: EasyCorp/EasyAdminBundle

Hi,
this is my admin.yml file:

    entities:
      Taller:
            label: app.talleres
            class: AppBundle\Entity\Taller
        User: 
            label: app.usuarios
            class: AppBundle\Entity\User
            list:
                title: "User list"
                fields: ['username', 'email', 'language','Taller','lastLogin', 'enabled', 'locked']
                actions: ['-show']
            form:
                fields:
                    - { property: 'username' , label: 'app.users.username' }
                    - { property: 'email', type: 'email' , label: 'app.users.email' }
                    - { property: 'language', type: 'choice', choices:['Euskera','Castellano'], label: 'app.users.language' }
                    - { property: 'taller' , label: 'app.users.taller' }
                    - { property: 'plainPassword', type: 'password', label: 'Password', help: 'Passwords must have at least 8 characters' , label: 'app.users.plainPassword' }
                    - { property: 'enabled', type: 'checkbox' , label: 'app.users.enabled' }
                    - { property: 'locked', type: 'checkbox', label: 'app.users.locked' } 

I want to display a language selector with two options: 'Euskera' and 'Castellano'. The form is rendering correctly but no value is printed to the select html. Is my admin.yml correct?

I also tried with

    - { property: 'language', type: 'choice', choices:{'Euskera','Castellano'}, label: 'app.users.language' }
    - { property: 'language', type: 'choice', choices:{Euskera:'Euskera',Castellano:'Castellano'}, label: 'app.users.language' }
    ...

any help or clue?
thanks in advance

Most helpful comment

Another option is to define your choices in a parameter

eg. in services.yaml

parameters:
   status:
        Active: 1
        Inactive: 0

in easy_admin.yaml

- { property: 'status', type: 'choice', type_options: { expanded: true, choices: '%status%' }}

All 6 comments

If you want to do it in the cleanest way, you'll have to wait until #323 is merged.

But actually, you can do it by overriding the form in your controller.

Here is what I have in one of my backends for this:

# app/config/easyadmin.yml
easy_admin:
    entities:
        MyEntity:
            form:
                fields:
                    - { property: locale, type: choice, choices: [ en, fr, de, es ] }
<?php

namespace AdminBundle\Controller;

use Doctrine\ORM\Mapping\ClassMetadataInfo;
use JavierEguiluz\Bundle\EasyAdminBundle\Controller\AdminController as BaseAdminController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Kernel;

class AdminController extends BaseAdminController
{
    /**
     * @Route("/", name="admin")
     * {@inheritdoc}
     */
    public function indexAction(Request $request)
    {
        return parent::indexAction($request);
    }

    /**
     * {@inheritdoc}
     */
    public function createEntityForm($entity, array $entityProperties, $view)
    {
        $formCssClass = array_reduce($this->config['design']['form_theme'], function ($previousClass, $formTheme) {
            return sprintf('theme_%s %s', strtolower(str_replace('.html.twig', '', basename($formTheme))), $previousClass);
        });
        $formBuilder = $this->createFormBuilder($entity, array(
            'data_class' => $this->entity['class'],
            'attr' => array('class' => $formCssClass, 'id' => $view.'-form'),
        ));
        foreach ($entityProperties as $name => $metadata) {
            $formFieldOptions = array();
            if ('association' === $metadata['fieldType'] && in_array($metadata['associationType'], array(ClassMetadataInfo::ONE_TO_MANY, ClassMetadataInfo::MANY_TO_MANY))) {
                continue;
            }
            if ('collection' === $metadata['fieldType']) {
                $formFieldOptions = array('allow_add' => true, 'allow_delete' => true);
                if (version_compare(Kernel::VERSION, '2.5.0', '>=')) {
                    $formFieldOptions['delete_empty'] = true;
                }
            }
            $formFieldOptions['attr']['field_type'] = $metadata['fieldType'];
            $formFieldOptions['attr']['field_css_class'] = $metadata['class'];
            $formFieldOptions['attr']['field_help'] = $metadata['help'];

            //------------------------------------------------------------------
            //------------------------------------------------------------------
            // Overrides
            if (isset($metadata['choices'])) {
                $formFieldOptions['choices'] = array_combine($metadata['choices']), $metadata['choices']));
            }
            // End overrides
            //------------------------------------------------------------------
            //------------------------------------------------------------------

            $formBuilder->add($name, $metadata['fieldType'], $formFieldOptions);
        }
        return $formBuilder->getForm();
    }
}

All the code outside the overrides comments is copy/pasted from the AdminController from my vendor dir, so I'm sure it fits totally to the used version.

It's totally ugly, but this way, you can optimize the form the way you want, better than just overriding the Form object returned by the parent createEntityForm method. In fact it would be easier if the createEntityForm returned a FormBuilder instance, but actually it's what I intend to do in #399

It works perfectly! thanks for your help @Pierstoval !

For reference, I found a few typos in your code:

<?php

namespace AdminBundle\Controller;

use Doctrine\ORM\Mapping\ClassMetadataInfo;
use JavierEguiluz\Bundle\EasyAdminBundle\Controller\AdminController as BaseAdminController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Kernel;

class AdminController extends BaseAdminController
{
    /**
     * @Route("/", name="admin")
     * {@inheritdoc}
     */
    public function indexAction(Request $request)
    {
        return parent::indexAction($request);
    }

    /**
     * {@inheritdoc}
     */
    protected function createEntityForm($entity, array $entityProperties, $view)
    {
        $formCssClass = array_reduce($this->config['design']['form_theme'], function ($previousClass, $formTheme) {
            return sprintf('theme_%s %s', strtolower(str_replace('.html.twig', '', basename($formTheme))), $previousClass);
        });
        $formBuilder = $this->createFormBuilder($entity, array(
            'data_class' => $this->entity['class'],
            'attr' => array('class' => $formCssClass, 'id' => $view.'-form'),
        ));
        foreach ($entityProperties as $name => $metadata) {
            $formFieldOptions = array();
            if ('association' === $metadata['fieldType'] && in_array($metadata['associationType'], array(ClassMetadataInfo::ONE_TO_MANY, ClassMetadataInfo::MANY_TO_MANY))) {
                continue;
            }
            if ('collection' === $metadata['fieldType']) {
                $formFieldOptions = array('allow_add' => true, 'allow_delete' => true);
                if (version_compare(Kernel::VERSION, '2.5.0', '>=')) {
                    $formFieldOptions['delete_empty'] = true;
                }
            }
            $formFieldOptions['attr']['field_type'] = $metadata['fieldType'];
            $formFieldOptions['attr']['field_css_class'] = $metadata['class'];
            $formFieldOptions['attr']['field_help'] = $metadata['help'];

            //------------------------------------------------------------------
            //------------------------------------------------------------------
            // Overrides
            if (isset($metadata['choices'])) {
                $formFieldOptions['choices'] = array_combine($metadata['choices'], $metadata['choices']);
            }
            // End overrides
            //------------------------------------------------------------------
            //------------------------------------------------------------------

            $formBuilder->add($name, $metadata['fieldType'], $formFieldOptions);
        }
        return $formBuilder->getForm();
    }
}

Though maybe createEntityForm visibility was indeed public in your EasyAdmin version, I don't know if this one changed recently.

Thanks for that snippet, that helps a lot while waiting for the other PR :)

You're right, the method should be protected anyways.
And thanks for correcting the typo for the choices field.

At least you could explain the proper diff, it could have been more "verbose" :wink:

Another option is to define your choices in a parameter

eg. in services.yaml

parameters:
   status:
        Active: 1
        Inactive: 0

in easy_admin.yaml

- { property: 'status', type: 'choice', type_options: { expanded: true, choices: '%status%' }}

choices should be in type_options, not outside ;)

Was this page helpful?
0 / 5 - 0 ratings