【问题标题】:symfony 5 form entitytype filter choices based on other entitytype choice selectedsymfony 5 表单实体类型过滤器选择基于选择的其他实体类型选择
【发布时间】: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',                
])

【问题讨论】:

    标签: forms symfony many-to-many entity


    【解决方案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。
    猜你喜欢
    • 1970-01-01
    • 2014-04-15
    • 2018-03-28
    • 2021-11-08
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 2016-03-20
    • 1970-01-01
    相关资源
    最近更新 更多