Symfony2:使用请求中的信息动态添加表单字段

时间:2013-02-12 13:49:14

标签: symfony symfony-forms

情景:

  1. 第1步:从某些古老的Web服务中获取信息
  2. 第2步:在表单中添加x单选按钮,而x取决于来自Web服务的信息
  3. 我知道我应该添加一个事件订阅者类,如in the documentation

    所示

    $ event有一个setData方法。可能我必须使用它。如何从控制器访问此方法?

    其他信息: 我在使用Doctrine。目前我正在创建一个Doctrine实体并将其传递给如下形式:

    $product = new Product(); $form = $this->createForm(new ProductType(), $product);
    

2 个答案:

答案 0 :(得分:0)

您不必在$ event对象上使用setData()。您需要实施on POST_SET_DATA逻辑,根据您的数据构建表单the way you want

然后,您可以使用网络服务的回复初始化您的表单(在您的控制器内)。

注意:自版本2.1以来,不推荐使用SET_DATA表单事件。它将在版本2.3中被删除)

<强>更新

您可以将数组设置为表单数据,并使用DataTransformer按照您希望的方式构建表单数据。在上次旧金山Symfony Live期间,请查看Data Transformation part Symfony 2 Form Tricks

答案 1 :(得分:0)

这是我最终解决的问题。不确定这是否是最佳方式,因此这个答案没有标记为正确,以鼓励其他更多体验Symfony用户提出更好的解决方案。

我不喜欢这个解决方案,我不能再将整个产品实体传递给表单,但必须将每个属性分别添加到options数组中:

无论如何,这就是它现在的实施方式:

动态数据使用options数组作为createForm()的第二个参数传递:

  // ExampleController.php

  use Acme\ExampleBundle\Entity\Product;
  public function addAction()
  {
     // choices contains the dynamic data I am fetching from the webservice in my actual code
     $choices = array("key1" => "value1", "key2" => "value2");

     // now create a new Entity
     $product = new Product();

     // and some attributes already have values for some reason
     $product->setPrice(42);

     $form = $this->createForm(new AddproductType(), 
              array(
                 "choices" => $choices,
                 "price"   => $product->getPrice() 
               )
            );
     if ($request->isMethod('POST')) {
        $form->bind($request);
        if ($form->isValid()) {
          // ... standard symfony stuff here
        }
     }
    return array(
        'form' => $form->createView()
    );
 }

现在为表单类。请注意事件侦听器部分和setDefaultOptions方法。

// ProductType.php

namespace Acme\ExampleBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;


class ProductType extends AbstractType
{

  public function buildForm(FormBuilderInterface $builder, array $options)
  {
    $formFactory = $builder->getFormFactory();
    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function (\Symfony\Component\Form\FormEvent $event) use ($formFactory) {

                // get the option array passed from the controller
                $options = $event->getData();

                $choices = $options["choices"];
                $event->getForm()->add(
                // add a new element with radio buttons to the form
                $formFactory->createNamed("my_dynamic_field_name", "choice", null, array(
                        "empty_value" => "Choose an option",
                        "label" => "My dynamic field: ",
                        "choices" => $choices
                    )
                )
            );

        }
    );

    // ... add other form elements
    $builder->add("price", "text");
    // ..
 }

 public function setDefaultOptions(OptionsResolverInterface $resolver)
 {
    // register choices as a potential option
    $resolver->setDefaults(array(
        'choices' => null
    ));
 }
}