Symfony2 Custom Form Type or Extension

2019-09-01 01:55发布

An Entity Order exists with a property Product.

A form has been created OrderType that allows a Product to be added to an Order.

This works, however it's not very interesting.

Instead of showing a simple Product drop down, it should be an autocomplete.

However when choosing an autocomplete value some additonal fields should be populated with information about the product.

Choosing a product from the autocomplete should populate two additional fields with Price and Code.

The controller method to return the data has aleady been created and jquery have some handy autocomplete functions avaiable.

I know how to hack the solution directly into the form template but I would like to make a reusable component.

The question is how do I create a custom form or extension with this behaviour?

class Order {
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\ManyToOne(targetEntity="Product", inversedBy="orders", cascade={"persist"})
     * @ORM\JoinColumn(name="product_id", referencedColumnName="id")
     */
    protected $product;  

    protected $quantity;
}

class Product {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\OneToMany(targetEntity="Product", mappedBy="product")
     */
    protected $orders;

    protected $name;
    protected $price;
    protected $code;
}

class OrderType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
            ->add('quantity')
            ->add('product');    
    }
}

Update I have updated OrderType with the following:

    $builder
        ->add('ppprice', 'text', array('mapped' => false, 'data' => 2));

    $builder->addEventListener(
        FormEvents::PRE_SET_DATA, function (FormEvent $event) use($builder) {
        $form = $event->getForm();
        $order = $event->getData();
        $builder
            ->add('ppprice', 'text', array('mapped' => false, 'data' => 21));
        $builder
            ->add('test', 'text', array('mapped' => false, 'data' => 21));
    }
    );

PRE_SET_DATA is being called but the new form field test is never added and ppprice is not updated with the new value.

How do I get PRE_SET_DATA to update the value?

1条回答
贪生不怕死
2楼-- · 2019-09-01 02:35

You should attach a FormEvent that handles the POST_SUBMIT event on your forms. There's a tutorial with a full example (incl. jquery ajax behavior) here:
http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html

This will take care of adding dynamic fields to your FormType. You can create an EventListener if you are looking to re-use this later, or you can attach the event via Closures when building your custom form type.

Update:

Try the following code first to see and check if the PRE_SET_DATA event properly kicks in. Please note that you can not inject $builder into this Closure. (You can but won't work) Simply use the $form object and ->add fields in the Closure like this:

$builder->addEventListener(
        FormEvents::PRE_SET_DATA, function (FormEvent $event) {
        $form = $event->getForm();
        $order = $event->getData();

        $form->add('ppprice', 'text', array('mapped' => false, 'data' => 21));
        $form->add('test', 'text', array('mapped' => false, 'data' => 21));
    }
    );
查看更多
登录 后发表回答