0

设想:

  1. 第 1 步:从一些古老的 Web 服务中获取信息
  2. 第 2 步:在我的表单中添加 x 单选按钮,而 x 取决于来自 Web 服务的信息

我知道我应该添加一个事件订阅者类,如文档中所示

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

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

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

2 回答 2

0

You don't have to setData() on the $event object. You've to implement an on POST_SET_DATA logic that builds your form the way you want according to you data.

You've then to initialize your form (inside your controller) using your webservice's reply.

(Note: SET_DATA form event is deprecated since version 2.1. It'll be definitely removed in version 2.3)

Update:

You can set an array as form data and use a DataTransformer to structure your form's data the way you want. Take a look at the Data Transformation part of Symfony 2 Form Tricks during the last San Francisco Symfony Live.

于 2013-02-12T14:02:26.737 回答
0

这是我最终得到的解决方案。不确定这是否是最好的方法,所以这个答案没有被标记为正确,以鼓励其他更有经验的 Symfony 用户提出更好的解决方案。

我不喜欢这个解决方案的地方是,我不能再将整个产品实体传递给表单,而是必须将每个属性单独添加到选项数组中:

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

动态数据使用 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
    ));
 }
}
于 2013-02-24T12:59:44.813 回答