Symfony2嵌入式表单+动态表单更新

时间:2013-09-06 16:00:03

标签: forms symfony symfony-2.2

我的表单中有一个下拉菜单,表单结构取决于它的值。我已设法用事件订阅者/侦听器类解决“form-update-issue”,我试图根据下拉列表的值来更新主窗体。

主要问题是我必须从数据库中持久存在的值修改表单。 我的数据库架构:

我有4个表:模型 ModelCategory ModelCategoryKey ModelParameter

  • ModelCategory 1 - n Model 1 - m ModelParameter
  • ModelCategory 1 - n ModelCategoryKey
  • ModelCategoryKey 1 - n ModelParameter

用户从表单(基于模型实体的表单)下拉列表中选择一个ModelCategory后,我必须使用ModelParamater行更新表单,但它的数字和默认值取决于ModelCategory 1 - n ModelCategoryKey assocaiton。

我试图在PRE_BIND事件期间将新的ModelParameter实体附加到主模型实体(也设置它们的默认值)并且看起来工作正常,但是当我添加带有'collection'类型元素的'parameters'时表格我得到了下一个错误:

  

必须管理传递到选择字段的实体。也许坚持他们在实体经理?

显然,我的实体此时不能(也不应该)持久存在。

欢迎所有想法!

更新 在preSubmit / preBind之后修改表单:

$form->add('parameters','collection',array(
    'type' => new ModelParameterType(),         
));

OR

$form->add(
            $this->factory->createNamed('parameters','collection',null,
                array(
                    'type' => new ModelParameterType()
                    ))
        );

其中'factory'属性是FormFactoryInterface。错误消息是相同的。

UPDATE2:

进一步调查证明,如果我不向关联添加“默认”实体。然后它可以正常工作。

以下是我的表单修改方法的来源:

public function preSubmit(FormEvent $event) {
    $form = $event->getForm();  
    $id = $event->getData()['modelCategory'];       
    $entity = $form->getData();
    $categoryKeys = $this->em->getRepository('MyBundle:ModelCategoryKey')->findByModelCategory(
        $this->em->getReference('MyBundle:modelCategory',$id)
    );      
    foreach ($categoryKeys as $key) {
        $param = new ModelParameter();
        $param->setModel($entity);
        $param->setKey($key); 
        $entity->addParameter($param);
    }

    $form->add(
        $this->factory->createNamed('parameters','collection',null,
            array(
                'type' => new ModelParameterType(),
                'allow_add' => true,
                'cascade_validation' => true
                ))
    );

}

要解决的问题 我刚刚注释掉了$ param-> setModel($ entity);线,它似乎工作正常。如果真的有效的话,我会更多地解决这个问题并分享经验。

2 个答案:

答案 0 :(得分:0)

choice字段仅接受托管实体,因为该值在提交后设置为实体,并且仅列出实体ID,因此必须事先保存。

您不需要选择字段 - 您需要收集参数子表单。

$formBuilder
    ->add('category', 'category_select')
    ->add('parameters', 'collection', array('type' => 'parameter'))
;

我假设category_select是带有类别的选择字段,parameter是带有自己值的子表单,具体取决于您的参数结构。

如果控制器中有类别,则可以将新创建​​的实体与添加的参数实体绑定,并设置key,具体取决于ModelCategoryKey。

答案 1 :(得分:0)

我设法解决了我的问题,所以这就是我发现的:

  • 通过反面的加法器函数添加新创建的对象就足够了。我没有必要打电话给拥有方的人。
  • 必须修改反面加法器功能,它会调用拥有方的设置器。
  • 反面加法器函数必须检查对象是否已经在集合中。
  • 创建表单时发生PRE_SET_DATA事件。 (所以在新实体中它是空的,在旧实体中它是填充的)