symfony 5 表单实体类型过滤器选择基于选择的其他实体类型选择

Posted

技术标签:

【中文标题】symfony 5 表单实体类型过滤器选择基于选择的其他实体类型选择【英文标题】:symfony 5 form entitytype filter choices based on other entitytype choice selected 【发布时间】:2022-01-20 11:17:19 【问题描述】:

在 Symfony 5 中的 FormType 或 Controller。 如何根据另一个实体类型的选定选项过滤实体类型选项。 这 2 个实体以多对多关系关联。

->add('player', EntityType::class, [                
    'class'        => Player::class, 
    'choice_label' => 'name',
    'label'        => 'select player',                
])

->add('game', EntityType::class, [                
    'class'        => Game::class, 
    'choice_label' => 'name',
    'label'        => 'select game',                
])

【问题讨论】:

【参考方案1】:

在 Symfony 中不可能开箱即用,但您可以使用 jQuery(或等效的 js 实现)和表单事件来实现。

Symfony 文档中有一个非常相似的示例,其中包含 Sports 并且取决于所选的 Sport - Positions:https://symfony.com/doc/current/form/dynamic_form_modification.html#dynamic-generation-for-submitted-forms

表单文件应如下所示:

// src/Form/Type/SportMeetupType.php
namespace App\Form\Type;

use App\Entity\Position;
use App\Entity\Sport;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormInterface;
// ...

class SportMeetupType extends AbstractType

    public function buildForm(FormBuilderInterface $builder, array $options): void
    
        $builder
            ->add('sport', EntityType::class, [
                'class' => Sport::class,
                'placeholder' => '',
            ])
        ;

        $formModifier = function (FormInterface $form, Sport $sport = null) 
            $positions = null === $sport ? [] : $sport->getAvailablePositions();

            $form->add('position', EntityType::class, [
                'class' => Position::class,
                'placeholder' => '',
                'choices' => $positions,
            ]);
        ;

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($formModifier) 
                // this would be your entity, i.e. SportMeetup
                $data = $event->getData();

                $formModifier($event->getForm(), $data->getSport());
            
        );

        $builder->get('sport')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) use ($formModifier) 
                // It's important here to fetch $event->getForm()->getData(), as
                // $event->getData() will get you the client data (that is, the ID)
                $sport = $event->getForm()->getData();

                // since we've added the listener to the child, we'll have to pass on
                // the parent to the callback functions!
                $formModifier($event->getForm()->getParent(), $sport);
            
        );
    

    // ...

和模板文件:

# templates/meetup/create.html.twig #
 form_start(form) 
     form_row(form.sport)     # <select id="meetup_sport" ... #
     form_row(form.position)  # <select id="meetup_position" ... #
    # ... #
 form_end(form) 

<script>
var $sport = $('#meetup_sport');
// When sport gets selected ...
$sport.change(function() 
  // ... retrieve the corresponding form.
  var $form = $(this).closest('form');
  // Simulate form data, but only include the selected sport value.
  var data = ;
  data[$sport.attr('name')] = $sport.val();
  // Submit data via AJAX to the form's action path.
  $.ajax(
    url : $form.attr('action'),
    type: $form.attr('method'),
    data : data,
    complete: function(html) 
      // Replace current position field ...
      $('#meetup_position').replaceWith(
        // ... with the returned one from the AJAX response.
        $(html.responseText).find('#meetup_position')
      );
      // Position field now displays the appropriate positions.
    
  );
);
</script>

祝你好运,请随时在 cmets 中询问更多详细信息 :)

【讨论】:

@MarcoBonelli 你是对的,我编辑了我的答案。 感谢 k1000 的详细解答。我会试一试,然后告诉你。 该示例运行良好。非常感谢 k1000。

以上是关于symfony 5 表单实体类型过滤器选择基于选择的其他实体类型选择的主要内容,如果未能解决你的问题,请参考以下文章

Symfony2 表单 > 实体字段类型 > 查询构建器 > 可能的子选择?

带有文件类型字段editAction的Symfony 3表单集合实体

Symfony 表单 - EntityType 通过实体 ID 选择选项

动态表单(切换实体)symfony2

Symfony 表单插入通过 Select2 选择的多个值

Symfony:必须管理传递给选择字段的“App\Entity\Classement”类型的实体。也许您忘记将其保留在实体管理器中?