【问题标题】:Symfony Form EventListener not triggeringSymfony 表单事件监听器未触发
【发布时间】:2021-03-17 08:16:25
【问题描述】:

我是 Symfony 的新手,我的表单有问题。 我正在尝试用拳头的选定项目填充下拉列表。

到目前为止,我能够用数据填充第一个,并为第二个设置了 EventListener。

我一直坚持从所做的选择中展示和填充它。 我遵循了 Symfony 教程中的 indications

这是我的表单类型:

public function buildForm(FormBuilderInterface $builder, array $options)
{       
    // Getting the Site(s) linked tu the User
    $sites = $this->controller->getSitesByUser();

    $builder
        ->add('site', EntityType::class,[
            'class' => Site::class,
            'data' => $sites,
            'label' => 'Site : ',
            'placeholder' => 'Choisissez un Site',
            'choice_label' => function($sites){
                return sprintf('%s',$sites->getNom());
            }
        ])
        ->add('appel', EntityType::class,[
            'class' => Appel::class
        ])
        ->add('startDate', DateType::class, [
            'label' => 'Date début :',
            'widget' => 'single_text',
            'attr' => ['class' => 'js-datepicker'],
            'label' => 'Date début :'
        ])
        ->add('endDate', DateType::class, [
            'label' => 'Date fin :',
            'widget' => 'single_text',
            'attr' => ['class' => 'js-datepicker'],
            'label' => 'Date fin :'
        ])
        ->add('generate', SubmitType::class, [
            'label' => 'Generer'
        ])
        ->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData'))
        ->getForm();
}

function onPreSetData(FormEvent $event) {
    // GetData return a Fact Object
    $form = $event->getForm();

    // Get selected field from 'site'
    $entityObject = $form->get('site')->getData();
    // Get the id of the selected object
    if($entityObject != null){
        $selectedSite = $entityObject->getId();
    }else $selectedSite = null;

    //dd($selectedSite);
    //$appels = $this->controller->getPostesBySite($selectedSite);

    $this->addElements($form, $selectedSite);

}

private function addElements(FormInterface $form, $selectedSite){
    if (null === $selectedSite) {
        $form->remove('appel');
        return;
    }
    // Only if the user has selected a Site Entity
    if($selectedSite){
        $form->add('appel', EntityType::class,[
            'class' => Appel::class,
            'placeholder' => 'Sélectionnez un Poste',
            'label' => 'Poste : ',
            'multiple' => true,
            'required' => false,
            'query_builder' => function (AppelRepository $ar) use ($selectedSite) { // Variable to use in use (sic)
                return $ar->createQueryBuilder('u')
                    ->select('u')
                    ->where('u.site = :idSite')
                    ->orderBy('u.from_dispname', 'ASC')
                    ->setParameter('idSite', $selectedSite);
            },
        ]);
    }
    
}

public function configureOptions(OptionsResolver $resolver): void{
    $resolver->setDefaults([
        'data_class' => Fact::class,
    ]);
}

和我的控制器:

public function createfact(Request $request, $id, UserInterface $user = null) : Response {
    $fact = new Fact();
    $fact->setName('Facture n° '.$fact->getId(). 'par '.$fact->getUser());
    $fact->setDate(new \DateTime());

    $form = $this->createForm(FactFormType::class, $fact);

    $form->handleRequest($request);

    return $this->render('main/fact.html.twig', [
        'formFact' => $form->createView()
    ]);
}

在我的树枝上:

{% block body %}
{{ form_start(formFact) }}
    {#{{ form_widget(formFact) }}#}
    {{ form_row(formFact.site)}}
    {%  if formFact.appel is defined %}
        {{ form_row(formFact.appel) }}
    {% endif %}
    {{ form_row(formFact.startDate)}}
    {{ form_row(formFact.endDate)}}
    {{ form_row(formFact.generate)}}
{{ form_end(formFact) }}

{% 端块 %}

在块体中使用此脚本:

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

我错过了什么?

提前致谢。

【问题讨论】:

  • if($entityObject != null){ $selectedSite = $entityObject-&gt;getId(); return;} 这里的return; 背后的原因是什么?
  • 没有理由在这里。已删除,谢谢@zizoujab
  • 表单提交了吗?响应状态码是200? (您可以在 web profiler 中检查请求内容、状态和表单状态)
  • 是的,在分析器中加载状态为 200
  • 可能跑题了,但你不应该在 buildForm 方法结束时使用 getForm。

标签: php forms symfony


【解决方案1】:

如果找到解决方法,请遵循 Cerad 使用 JS 的想法。 正如我所说,这是一种解决方法,并且不使用 FormEvent。

我做的第一件事是将两个 DropDown 拆分为两个单独的 FormType。

然后,所有的处理都在 Twig 中完成:

{% 块体 %}

{{ form_start(formFact) }}
    {#{{ form_widget(formFact) }}#}
    {{ form_widget(formFact) }}
    {{ form_widget(formFact2) }}
    <button type="submit" class="btn btn-primary">Générer la Facture</button>
{{ form_end(formFact) }}

<script>
    $(document).ready(function(){ 
        $("#fact_form_site").change(function() {
            var vendor = $('#fact_form_site option:selected').val()
            var DATA = 'id=' + vendor;
            
            $.ajax({
                type: "POST",
                dataType: 'json',
                url:  '{{ (path('appelfact')) }}',
                data: DATA,
                success: function(msg){
                    $("#fact_form2_appel")                                                              // Getting the DropDown
                        .find('option')                                                                 // Finding <option>
                        .remove()                                                                       // Clearing the options from DropDown
                        .end()                                                                          // Commit changes
                        .append('<option value="" selected="selected">Sélectionnez un Poste</option>'), // Getting message back as first value
                    $.each(msg, function (i, value) {
                        var html='<option value="'+i +'">' + value + '</option>'
                        $("#fact_form2_appel").append(html);
                    });
                }
            });
        }); 
    });
</script>

{% 端块 %}

还有我稍微修改过的控制器:

/**
 * @Route("main/fact/{id}", defaults={"id" = null}, name="fact")
 */
public function createfact(Request $request, $id) : Response {
    $form = $this->createForm(FactFormType::class);
    $form2 = $this->createForm(FactForm2Type::class);


    $form->handleRequest($request);
    if ($form->isSubmitted() && $form->isValid()) {
        dd($form->getData());
    }

    return $this->render('main/fact.html.twig', [
        'formFact' => $form->createView(),
        'formFact2' => $form2->createView()
    ]);
}

这行得通,我添加了一些行来清除选择之间的下拉菜单。 如果它可以帮助某人,这比使用 FormEvent 简单得多。

【讨论】:

    【解决方案2】:

    您的控制器不发送表单。你忘了做 if ($form-&gt;submit &amp;&amp; $form-&gt;isValid) 和你的情况

    【讨论】:

    • 事实上,双关语是,PRE_SET_DATA event 是在表单创建过程中发送的。猜错了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-19
    相关资源
    最近更新 更多