存在包含属性Product的实体订单。
表单已创建OrderType,允许将产品添加到订单。
这很有效,但不是很有趣。
而不是显示简单的产品下拉列表,它应该是自动完成功能。
但是,在选择自动填充值时,应使用有关产品的信息填充一些附加字段。
从自动填充中选择产品时,应使用价格和代码填充另外两个字段。
已经创建了返回数据的控制器方法,并且jquery可以使用一些方便的自动完成功能。
我知道如何直接将解决方案破解到表单模板中,但我想制作一个可重用的组件。
问题是如何使用此行为创建自定义表单或扩展名?
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');
}
}
更新 我已使用以下内容更新OrderType:
$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,但从未添加新的表单字段测试,并且不会使用新值更新ppprice。
如何让PRE_SET_DATA更新值?
答案 0 :(得分:1)
您应该在表单上附加处理FormEvent
事件的POST_SUBMIT
。
这里有一个完整示例(包括jquery ajax行为)的教程:
http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html
这将负责为您的FormType
添加动态字段。如果您希望稍后重复使用,可以创建EventListener
,也可以在构建自定义表单类型时通过Closures
附加事件。
<强> 更新 强>
首先尝试使用以下代码查看并检查PRE_SET_DATA事件是否正常启动。请注意,您无法将$builder
注入此Closure
。 (您可以但不会工作)只需使用$form
中的->add
对象和Closure
字段,就像这样:
$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));
}
);