根据另一个字段中的选择将实体加载到字段中Symfony PRE_SET_DATA事件监听器

时间:2018-11-06 07:30:15

标签: php forms symfony entity

嗨,我得到了我的OrderType表单。

这是我的代码:

public function buildForm(FormBuilderInterface $builder, array $options)
{
   $builder
              ->add('client', EntityType::class, array(
              'data' => $options['client'],
              'mapped' => false,
              'attr' => ['class' => 'chosen-select','data-placeholder'=>'Wybierz klienta'],
              'class' => UserDetails::class,
              'choice_label' => function ($client) {
              return  ''.$firma.' '.$client->getJson()["client"]["imie"] .' '. $client->getJson()["client"]["nazwisko"].'';
               },
              'label' => 'Wybierz klienta'))


               ->add('save', SubmitType::class, [
               'label' => 'Zapisz',
               'attr' => ['class' => 'btn btn-primary pull-right']]) ;

    $builder->addEventListener( 
              FormEvents::PRE_SET_DATA,
                function (FormEvent $event) {
                       $form = $event->getForm();
                       $client =$form->get('client')->getData();
                       $shipping = null === $client ? array() : $client->getClientsShippings()->getJson()["clients_shippings"]["name"];

           $form->add('shipping', EntityType::class, array(
               'class' => ClientsShippings::class,
               'placeholder' => '',
               'choices' => $shipping));
             }
           );
}

没有错误,但是也没有任何反应。我不知道如何实现,选择EventListener客户端后,PRE_SET_DATA会根据所选客户端将分配给客户端的送货地址加载到ClientsShippings实体中。 我在symfony.com上读过几次,但我无法完全理解这些事件。

有人可以帮我运行它,让我举一个它如何工作的例子。也许我完全以不同的方式思考它。


  public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
                ->add('client', EntityType::class, array(
    'data' => $options['client'],
    'mapped' => false,
    'attr' => ['class' => 'chosen-select','data-placeholder'=>'Wybierz klienta'],
    'class' => UserDetails::class,
    'choice_label' => function ($client) {
      if(isset($client->getJson()["client"]["firma"]))
      {
        $firma = $client->getJson()["client"]["imie"];
        }
        else {
          $firma = "";
          }
    return  ''.$firma.' '.$client->getJson()["client"]["imie"] .' '. $client->getJson()["client"]["nazwisko"].'';
      },
    'label' => 'Wybierz klienta'

                ))

        ->add('product', EntityType::class, array(
    'data' => $options['product'],
    'mapped' => false,
    'multiple' => true,
    'class' => Products::class,
    'attr' => ['class' => 'chosen-select','data-placeholder'=>'Wybierz produkt'],
    'choice_label' => function ($product) {
        return  ''.$product->getJson()["products"]["name"] .' | Stan Magazynowy: '.$product->getJson()["products"]["stock"].'';
      },
  'label' => 'Wybierz produkty'

        ))

            ->add('save', SubmitType::class, [
            'label' => 'Zapisz',
            'attr' => ['class' => 'btn btn-primary pull-right']])
        ;

    $builder->get('client')->addEventListener(
      FormEvents::POST_SUBMIT,
      function (FormEvent $event)
      {
        $form = $event->getForm();

        $form->getParent()->add('shipping', EntityType::class, [
          'class' => ClientsShippings::class,
          'placeholder' => 'Wybierz adres dostawy',
          'choices' => $form->getData()->getclientsShippings()
        ]);
      }
    );


    }

1 个答案:

答案 0 :(得分:1)

Symfony表单有两种主要用法:

  1. 创建新实体(称为Form::submit()
  2. 编辑现有实体(称为Form::setData()Form::Submit()

注意:在两种情况下,Form::handleRequest()都会在Form::submit()之前被调用,以检查请求是否可以提交。

我们有2个主要的表单事件类别:

  • 预填充表单期间的事件(仅用于编辑实体表单)
  • 表单提交过程中的事件(用于新建和编辑实体表单)

1。用模型数据预填充表单

PRE_SET_DATA

PRE_SET_DATA事件,获取您从其开始的数据的值(在您的情况下为Order对象),并在将实体对象的数据填充到表单之前立即调度。

您可以使用此事件执行以下操作:

  • 在填充期间修改表单数据
  • 添加或删除表单字段

POST_SET_DATA

此事件在调用Form::setData()方法之后立即触发,可用于:

  • 在预先填充表格后读取数据

POST_SET_DATAPOST_SET_DATA事件都是在预先填充表单数据时分派的。

2。表格提交

PRE_SUBMIT

在调用Form::submit()Form::handleRequest()时触发。此事件可用于:

  • 更改从请求中捕获的数据
  • 在提交数据之前添加或删除字段

提交

此事件在PRE_SUBMIT之后和Form::submit期间调度(在模型和视图数据归一化之后,以及反归一化之前)。您可以使用此事件执行以下操作:

  • 标准化后更改数据。

POST_SUBMIT 此事件在Form::submit()之后调度。您可以使用此事件执行以下操作:

  • 反规范化后获取数据。

回答您的问题

您应该使用2个事件侦听器,其中一个用于PRE_SET_DATA,另一个用于POST_SUBMIT

OrderType

class OrderType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('client', EntityType::class, array(
                'class' => UserDetails::class
            ))
            ->add('save', SubmitType::class)
        ;

        $modifier = function (FormInterface $form, Client $client = null) {
            $shippings = null === $client ? array() : $client->getClientsShippings();

            $form->add('shipping', EntityType::class, array(
                'class' => ClientsShippings::class,
                'choices' => $shippings,
            ));
        };

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($modifier) {
                $orderData = $event->getData();
                $modifier($event->getForm(), $orderData->getClient());
            }
        );

        $builder->get('client')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) use ($modifier) {
                $client = $event->getForm()->getData();
                $modifier($event->getForm()->getParent(), $client);
            }
        );
    }
}

根据所选的客户端,您还应该进行AJAX调用(某些JavaScript)以更新shipping列表。