我努力在问题的标题中表达我的意思!我会尽力在这里更有意义......
Symfony 2.7
我有一个表格,在提交并成功验证时,我想提供第二个独立表格,以便进一步开展用户活动。我希望第二种形式的初始值由第一种形式提供,但第二种形式则是独立的,例如它可以通过自己独立的提交/验证步骤。
我不想要:
从概念上讲,我希望能够验证第一个表单,然后在Controller中将收到的数据传递给另一个Action,这将向用户显示新表单。然后,新动作将处理进一步的用户提交。我觉得这应该是可能的,我只是不确定如何实现它!在某种程度上,我希望第二个Action是私有的,但它确实需要公开,以便可以提交第二个表单。我希望能够使用对象直接将数据传递给第二个Action,但我不想将该入口点公开为标准Route。
提前致谢。
答案 0 :(得分:0)
Sorry for any lack of clarity in the question. Here's how I solved it (I'd still be interested in any different/better solutions):
I created a separate FormType (ReportConfirmType
) and Action (ConfirmAction
) for the second step. ReportConfirmType
has the type of Data Class, and essentially all the same fields as the original FormType (ReportType
), but with them all marked readonly
. The route is very similar. I also created a private method to act as the "glue" between the first and second steps.
When I'm finished with my first step, I then call the private method, passing it the validated data from the first step (which can be used unchanged). This method sets up the second form and returns the second view. The action of the form needs to be changed to that of the second route.
All subsequent submissions will go to the new route, and when the second form validates I can carry out the final activities of the process.
Here's some example code to illustrate further:
ReportType
class ReportType extends AbstractType{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text')
->add('completedBy', 'text')
->add('comments', 'textarea', ['required' => false])
->add('format', 'choice', ['choices' => ['pdf' => 'PDF', 'word' => 'MS Word'] ])
->add('save', 'submit', ['label' => 'Submit', 'attr' => ['class' => 'btn btn-primary']])
->getForm();
}
...
ReportConfirmType
class ReportConfirmType extends AbstractType{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text', ['attr' => ['readonly' => 'readonly']])
->add('completedBy', 'text', ['attr' => ['readonly' => 'readonly']])
->add('comments', 'textarea', ['required' => false, 'attr' => ['readonly' => 'readonly']])
->add('format', 'choice', ['choices' => ['pdf' => 'PDF', 'word' => 'MS Word'], 'attr' => ['readonly' => 'readonly'] ])
->add('agree', 'checkbox', ['mapped' => false, 'label' => 'I agree', 'constraints' => [new IsTrue()]])
->add('save', 'submit', ['label' => 'Submit', 'attr' => ['class' => 'btn btn-primary']])
->getForm();
}
...
ReportController
class ReportController extends Controller
{
public function indexAction(Request $request, $id)
{
$form = $this->createForm(new ReportType(), new ReportDetails() );
$form->handleRequest($request);
if ($form->isValid()) {
return $this->confirmPseudoAction($id, $form);
}
return $this->render('Bundle:Report:index.html.twig', ['form'=> $form->createView()]);
}
private function confirmPseudoAction($id, \Symfony\Component\Form\Form $form)
{
$action = $this->generateUrl('form_confirm_report', ['id' => $id]);
$confirmForm = $this->createForm(new ReportConfirmType(), $form->getData(), ['action' => $action]);
return $this->render('Bundle:Report:confirm.html.twig', ['form'=> $confirmForm->createView()]);
}
public function confirmAction(Request $request, $id)
{
$form = $this->createForm(new ReportConfirmType(), new ReportDetails() );
$form->handleRequest($request);
if ($form->isValid()) {
return $this->generateReport($id, $form->getData());
}
return $this->render('Bundle:Report:confirm.html.twig', ['form'=> $form->createView()]);
}
...
routing.yml
form_report:
path: /form/{id}/report
defaults: { _controller: Bundle:Report:index }
requirements:
id: \d+
form_confirm_report:
path: /form/{id}/reportConfirm
defaults: { _controller: Bundle:Report:confirm }
requirements:
id: \d+
And this does what I want! There may be an easier way, but I've done it now...
答案 1 :(得分:0)