Symfony 2表单-添加新项目到集合服务器端,取决于按钮点击



我有一个表单,其中包含未指定数量的子表单的集合。我希望有一个功能,允许用户向Collection中添加一个新的空白项,供他们填写。Symfony文档告诉我们如何使用Javascript客户端来添加新的空白表单控件,然后像往常一样提交和持久化,但我想在控制器的服务器端完成它,不使用Javascript。

我遇到的问题是与Symfony窗体的工作方式有关。我在主表单中添加了一个"Add"按钮,我打算检测是否已经单击了该按钮,这样我就可以将空白项添加到Collection中并重新呈现表单。但是要检测点击,我需要调用$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

我想过的事情:

  • 将Add按钮放在同一页面上完全不同的表单中,它提交给不同的Action,然后在转发到上面的主Action之前可以做一些准备工作
  • 直接检查提交的HTTP数据,注意Add已被点击(遗憾没有使用标准的Symfony方法)
  • 放弃并使用Javascript作为建议(它可能在这个例子中工作,但我想有执行服务器端活动的选项(没有AJAX…)作为添加新的空白项的一部分)

我怎样才能以适当的Symfony方式最好地实现这一点?

编辑刚刚看到这个:https://github.com/symfony/symfony/issues/5231,这本质上是一个功能请求,以允许我所追求的。一位评论者提出的一个建议是在集合中添加一个空白项,然后在不需要的时候将其删除——我不知道如何做到这一点,但这听起来很有希望。

我突然想到,因为我需要我正在创建的$form的两个不同方面,我可能只是制作$form,用它来处理请求,检测按钮单击,然后扔掉$form,然后改变我的模型并创建另一个$form。我不知道这是否会违反处理两次提交的规则。

我不是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

我还没有测试过,所以我不知道它是否会触发表单错误(或者它是否会实际工作),所以如果它会(或不),我道歉

我最后所做的是让我的Add按钮点击一个单独的Action,然后将一个标记委托给主Action,表示"添加一个新选择",如下所示:

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);
    //...
}

最新更新