0

In the list field you can make a field editable by setting the attribute "editable" to "true" in the configureListFields action. Is it possible (with onboard sonata admin tools) to make a field editable that contains multiple values as in a one-to-many relation?

Example: I have a list of pupils listed in the list view. Every pupil has multiple classes listet in the classes column of the pupils list view. Via click on the classes I want a popover open (like it works with a normale string) with a suggest field like you can have it in the edit view.

Using the properties like in the configFormFields action doesn't work:

$listMapper->add(
                'classes',null, array(
                    'editable' => true,
                    'type' => 'sonata_type_model_autocomplete',
                    'multiple' => true,
                    'property' => 'name'
                )
            );

That snippet is written inside the PupilsAdmin class in the configureListFields action.

Is it possible or do I have to create a custom template? The documentation doesn't point me in the right direction: https://sonata-project.org/bundles/admin/2-2/doc/reference/field_types.html

Saerdn
  • 218
  • 2
  • 17

2 Answers2

1

If i understand you right, you want to edit a one-to-many relation inline in a list view of sonata. As far as i know, thats only possible for simple types like text, int or choices and so on. They point it out on no 18. in your link

Theses types accept an editable parameter to edit the value from within the list action. This is currently limited to scalar types (text, integer, url...).

So related objects can not be in that list, merely their scalar properties. For all other things you have to write your own template ...

I don't know what you want to achieve with this suggested list, but for me it makes no sense to edit a one-to-many property in the list view like its done in the edit view.

Jim Panse
  • 2,220
  • 12
  • 34
  • Thank you for your answer. "but for me it makes no sense to edit a one-to-many property in the list view like its done in the edit view." It's more efficient to edit the specific values right in the list instead of always edit the single entry. – Saerdn Oct 03 '17 at 12:14
  • Yes, thats right. But i can't imagine how this editable list entry will look like ... For example if there are several dozen classes, you have to display them for each record of your list view and make them multi-choicable ... – Jim Panse Oct 04 '17 at 07:18
  • But yes, maybe i am not that creative ^^ – Jim Panse Oct 04 '17 at 08:29
  • Actually I'd just imagine it being a simple textfield with all classes listed like its in the edit view. And if you start typing in that textfield you get more suggestions (again, like in the edit view :) ). So there would be no need for a multiple choice :) – Saerdn Oct 04 '17 at 10:44
  • Ok, i think you mean the edit view where you type 3 letters an choose one from listed ... the choice is than shown as a tag for this entity, right? But no, there is no inline feature for this, but you are welcome to implement a template taking the logic from edit view and add it to type guesser of the list view :P – Jim Panse Oct 04 '17 at 11:27
  • Yes, that's what I was referring to :) I'll try my best but I'm afraid it'll end up being a custom template/text field with some simple javascript Ajax calls ;) Which would be a very custom solution just for this one problem. – Saerdn Oct 04 '17 at 13:52
1

You just need to create new type. Something like "entity"

                'header_class' => 'col-lg-1',
                'class'        => Employee::class,
                'editable'     => true,
            ])

Next step is to override fixFieldDescription method in listBuilder and handle it

class EntityListBuilder extends ListBuilder
{
    /**
     * @var Registry
     */
    private $doctrine;

    /**
     * @param AdminInterface            $admin
     * @param FieldDescriptionInterface $fieldDescription
     */
    public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInterface $fieldDescription)
    {
        parent::fixFieldDescription($admin, $fieldDescription);

        if ($fieldDescription->getType() === 'entity') {
            $class = $fieldDescription->getOption('class');

            if (!$class) {
                throw new RuntimeException("Type entity must contain 'class' argument");
            }

            $objects = $this->doctrine->getRepository($class)->findAll();

            $choices = [];

            foreach ($objects as $object) {
                $choices[$object->getId()] = $object->__toString();
            }

            $fieldDescription->setOption('choices', $choices);
            $fieldDescription->setType('choice');
        }
    }

    /**
     * @param Registry $doctrine
     */
    public function setDoctrine(Registry $doctrine)
    {
        $this->doctrine = $doctrine;
    }

    /**
     * @param string $type
     *
     * @return string
     */
    private function getTemplate($type)
    {
        return $this->templates[$type] ?? '';
    }

Now, you have to override template for your "entity" type

{% extends '@SonataAdmin/CRUD/list_choice.html.twig' %}
{% set value = admin.id(value) %}

It's need to set already chosen value to select box Okay, last thing is to add our type to xeditable types of Twig Add it to OverrideServiceCompilerPass :

$definition           = $container->getParameter('sonata.admin.twig.extension.x_editable_type_mapping');
        $definition['entity'] = 'select';
        $container->setParameter('sonata.admin.twig.extension.x_editable_type_mapping', $definition);

And the last one just match your type with template


    templates:
        types:
            list:
                ...
                entity:        AppBundle:CRUD:list_entity.html.twig

Now you ready to edit it inline :)