简体   繁体   中英

Symfony 3.4 form EntityType selected value is empty

I have an issue with Symfony 3.4 EntityType.

CategoryType.php

class CategoryType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('spec', CollectionType::class, [
                'entry_type' => SpecificationType::class,
                'allow_add' => true,
                'allow_delete' => true,
                'label' => false,
            ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Category::class,
        ));
    }
}

SpecificationType.php

class SpecificationType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('title', EntityType::class, [
            'class' => Specification::class,
            'label' => false,
        ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Specification::class,
        ));
    }

    public function getBlockPrefix()
    {
        return 'specification';
    }
}

Form renders as expected: Title as Text field, and 2 select elements. But problem is rendered select element does not select selected value.

form.html.twig

{{ form_widget(form.title) }}
{{ form_widget(form.spec) }}

Result
在此处输入图片说明

Expected result
在此处输入图片说明

When in SpecificationType.php EntityType::class is replaced with TextField:class now form renders not 2 select elements bus 2 text inputs (expected behaviour) and values assigned are correct:
在此处输入图片说明

I started digging how these select elements are rendered in first place, and found that this block {%- block choice_widget_options -%} is responsible for rendering select element.

Inside this block is peace of code:

<option value="{{ choice.value }}"{% if choice.attr %}{% with { attr: choice.attr } %}{{ block('attributes') }}{% endwith %}{% endif %}{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans({}, choice_translation_domain) }}</option>

Exactly this condition: {% if choice is selectedchoice(value) %} selected="selected"{% endif %} is responsible for adding selected attribute to option. But value in selectedchoice(value) extension is somehow empty, that's why he is not marking option as selected.

Maybe anyone knows, how to solve this issue?

UPDATED

spec property is defined like this:

CategoryEntity.php

/**
 * @ORM\ManyToMany(targetEntity="Specification", inversedBy="categoryList")
 * @ORM\JoinTable(name="category_specification")
 */
private $spec;

Found solution here .

As @Nickolaus wrote:

[..] You are having this problem because it is a compound form in your implementation and no simple form and symfony is unable to resolve which field created inside the subform needs to be used as source for the entity field

So solution is:

Refactor SpecificationType.php like this:

class SpecificationType extends AbstractType
{
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'class' => Specification::class,
            'label' => false,
        ));
    }

    public function getParent()
    {
        return EntityType::class;
    }

    public function getBlockPrefix()
    {
        return 'specification';
    }
}

Use getParent() method, move all field configs to configureOptions and remove buildForm() method.

Finally.. so many hours wasted..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM