Symfony 2 Forms - 根据点击的按钮,将新项目添加到Collection服务器端

时间:2014-05-24 21:09:49

标签: forms symfony

我有一个表单,其中包含一个未指定数量的子表单的集合。我希望有一些功能允许用户向Collection中添加一个新的空白项目以供他们填写.Symfony文档告诉我们如何使用Javascript客户端添加新的空白表单控件,然后将其提交并保存为是的,但是我想在没有Javascript的情况下在控制器中执行它。

我遇到的问题与Symfony Forms的工作方式有关。我有一个"添加"按钮添加到我的主窗体,我打算检测是否是已单击的按钮,以便我可以将空白项添加到集合并重新呈现窗体。但要检测点击,我需要调用$ this-> createForm,此时表单已使用原始项目集修复,但添加额外的项目为时已晚。

//Symfony Action

//A Person has many Selections
$person = $this->getPerson($id)

//All fields are frozen at this point, according to data in $person!
$form = $this->createForm(new SelectionsType($lookups), $person);
$form->handleRequest($request);

//Ideally I'd somehow do this test earlier, but I need $form to do it...
if ($form->get('add')->isClicked() )
{
    //TOO LATE!
    $person->getSelections()->add(new Selection() );
}

if ($form->isValid())
{
    if ($form->get('save')->isClicked() )
    {
        //Persist
    }
}

//Render page etc

我曾经想过的事情:

  • 将“添加”按钮以完全不同的形式放在同一页面上,该页面提交不同的操作,然后可以在转发到上面的主要操作之前进行一些准备工作
  • 直接检查提交的HTTP数据,注意添加已被点击(羞于不使用标准的Symfony方法)
  • 按照建议放弃并使用Javascript(它可能适用于此示例,但我希望可以选择执行服务器端活动(不使用AJAX ...)作为添加新空白的一部分项)

如何以正确的Symfony方式实现这一目标?

编辑刚刚看到这个:https://github.com/symfony/symfony/issues/5231,这本质上是一个功能请求,允许我之后的内容。评论者提出的一个建议是在收藏中添加一个空白项目,如果不需要则将其删除 - 我不知道如何做到这一点,但听起来很有希望。

另一个编辑我发现,因为我需要创建$ form的两个不同方面,我可以只创建$ form,使用它来处理请求,检测按钮点击,以及然后扔掉那个$ form,然后改变我的模型并创建另一个$ form。我不知道这是否会以某种方式违反关于处理提交两次的一些规则。

2 个答案:

答案 0 :(得分:0)

我不是100%,但我认为你可以做到以下几点......

//Symfony Action with (Request $request, ...)

//A Person has many Selections
$person = $this->getPerson($id)

//All fields are frozen at this point, according to data in $person!
$form = $this->createForm(new SelectionsType($lookups), $person);

if ($request->isMethod('POST')) {
    $form->submit($request);

    if ($form->get('add')->isClicked()) {
        // Add thing
    } elseif ($form->isValid()) {
    // or 
    // } elseif ($form->get('save')->isClicked() && $form->isValid()) {
        // Persist and what not
    }
}

//Render page etc

我还没有测试过,所以我不知道它是否会触发表单错误(或者它是否真的有效)所以如果它确实(或者它没有)我道歉。

答案 1 :(得分:0)

我最后做的是让我的添加按钮点击一个单独的动作,然后用一个标志代表主动作说"添加一个新的选择",如下所示:

public function selectionsAddAction(Request $request, $id)
{
    return $this->selectionsAction($request, $id, true);
}

public function selectionsAction(Request $request, $id, $addNew = false)
{
    $person = $this->getPerson($id);

    //Also use "add mode" if we just deleted the last one!
    if (!$person->getSelections()->count())
    {
            $addNew = true;
    }

    //$addNew is set by a separate action, hit by a different form with the Add button in
    if ($addNew)
    {
        $person->getSelections()->add(new Selection() );
    }

    //We now have the right number of items, and can build the form!
    $form = $this->createForm(new SelectionsType($lookups), $person);

    //...
}