动态表单(切换实体)symfony2

Asb*_*tos 6 php ajax jquery symfony doctrine-orm

我正在制作广告页面.广告可以是不同类型的,因此具有不同的数据.例如,车辆将具有makemodel作为额外数据.

现在,我有一个基础学说实体Advert,其中包含每个广告所需的数据.反过来不同的广告就是这个数据(doctrine2 discriminatormap)

如果用户选择创建车辆广告,我需要动态填充表单(使用ajax和symfony2表单)我想显示车辆广告的选项.但我还需要将实体更改为形式AdvertVehicle.

这可能吗?我确实在symfony2主页上阅读了食谱

"如何使用表单事件动态修改表单":这应该通过向您的应用程序发回AJAX来处理.在该控制器中,您可以提交表单,但只需使用提交的表单呈现更新的字段,而不是处理它.然后可以使用AJAX调用的响应来更新视图.

我理解如何将ajax调用回我的控制器,并且我理解如何使用表单事件但是如何获得渲染的选择框(例如包含车辆模型)的响应?使用新的AbstractType?还是formbuilder?

然后,当用户实际提交表单时,我需要使用所选广告类型的实体.我可以根据表单中的用户选择动态更改实体吗?

编辑 我检查了表格遗传,这很好,谢谢.我扩展AdvertType和覆盖buildForm()方法,然后我添加我需要的项目,AdvertVehicleType我调用父方法.

Futher说明 每一个广告实体包含price,description,titlecategory.一些广告包含更多,例如makemodel.它们是由discriminatormap(doctrine2)区分的

例:

// -- Entity
class CarAdvert extends Advert {

    protected $model;
    protected $make;

}

// -- Entity
// -- This uses discriminator mapping
class Advert {
    protected $title;
    protected $description;
    protected $price;
    protected $category;
}
Run Code Online (Sandbox Code Playgroud)

如果用户选择cars我想要使​​用CarAdvert实体的类别(用于验证和持久性),如果用户选择了house hold itemcategory,我只想使用普通Advert实体.

一个主要问题仍然是我无法弄清楚如何通过ajax呈现扩展形式.关于这一部分的任何提示?当用户选择汽车作为类别时,我希望更新表单(通过jQuery/ajax)但是如何创建一个只检索表单扩展部分的控制器并将html作为响应发送回来(不使用twig)并在视图中呈现它,这可能吗?

解:

见下面的答案!

Asb*_*tos 2

解决方案:

我的问题的解决方案是在控制器中创建一些额外的函数来解决我希望能够从用户的选择中“动态”更改实体和表单的问题。

public function indexAction(Request $request)
{
    $form = $this->getForm($request);
    $form->handleRequest($request);

    return array(
           'form' => $form->createView(),
           'request' => $request->request,
    );
}
Run Code Online (Sandbox Code Playgroud)

其中getForm检索表单(例如,车辆的 AdvertVehicleType 或“默认”广告的 AdvertType)。

getForm方法如下所示:

 private function getForm(Request $request)
{
    $categoryTitle = 'NONE';
    $categoryId = $request->request->get('advert', false)['category'];

    if ($categoryId) {
        $categoryTitle = $this->getDoctrine()->getRepository('Bundle:Category')->find($categoryId)->getTitle();
    }

    return $this->createForm($this->getFormType($categoryTitle), $this->getEntity($categoryTitle));
Run Code Online (Sandbox Code Playgroud)

}

在这里,我检索categoryID(在请求的表单中选择的)并使用 getFormType 检索 formType 和使用 getEntity 检索实体。

private function getEntity($categoryTitle)
{
    $entity = new Advert();
    switch ($categoryTitle) {
        case Category::CARS:
            $entity = new AdvertCar();
    }

    return $entity;
}

private function getFormType($categoryTitle)
{
    switch ($categoryTitle) {
        case Category::CARS:
            return new AdvertCarType();
        default:
            return new AdvertType();
    }
}
Run Code Online (Sandbox Code Playgroud)

为了能够使用ajax“即时”更新此内容(但如果用户尝试提交表单,它也可以工作),我在控制器中创建了另一个操作。

此操作呈现我想要更新的表单部分(在 ajax 调用上),我通过使用 twig 将表单对象设置为呈现形式,实际挑选出表单中不需要的内容来实现此操作:

{% do form.title.setRendered %}
Run Code Online (Sandbox Code Playgroud)

(这只是一个例子,我实际上对所有我不想渲染的表单对象执行此操作。

然后我只需调用:

{{ form_rest(form) }}
Run Code Online (Sandbox Code Playgroud)

它将检索表单的“其余部分”,该部分对于不同类别是不同的。

现在假设您有州和城镇可供选择。首先选择州,然后在 twig 中渲染该州的城镇(但实际上你可以只渲染你需要的部分,例如,{{ form_row(form.towns) }}你将此渲染模板作为 json 响应返回,然后将其放入你想要的 div 中。

$html = $this->renderView('@Bundle/NewAddPage/filter_area.twig', array('form' => $form->createView()));
Run Code Online (Sandbox Code Playgroud)

然后在响应中返回 $html 变量。

我希望这有帮助,并且解释已经足够好了,如果不只是发表评论,我会用我的答案更新!