如何防止“确认表单重复提交”表单提交失败后弹出


How to prevent "confirm form resubmission" popup after failed form submission

当表单提交失败时,同样的表单会显示错误信息给用户,但是当他们按下F5或使用浏览器的后退/前进按钮时,会出现"确认重新提交"的弹出框。如何防止这种行为?

注意:我曾经在CodeIgniter中使用重定向方法而不会丢失错误消息,但我不知道如何处理Symfony中的相同类型的过程,因为我是新手。任何解决方案都是可以接受的。

控制器:

namespace Se'HirBundle'Controller;
use Symfony'Bundle'FrameworkBundle'Controller'Controller;
use Se'HirBundle'Entity'Task;
use Se'HirBundle'Form'Type'TaskType;
use Symfony'Component'HttpFoundation'Request;
use Symfony'Component'HttpFoundation'Response;
class TodoController extends Controller
{
    public function indexAction()
    {
        $task = new Task();
        $form = $this->createForm(new TaskType(), $task, array('action' => $this->generateUrl('todo_new')));
        return $this->render('SeHirBundle:Default:todo.html.twig',
                            array('page' => 'Todo', 'form' => $form->createView()));
    }
    public function newAction(Request $request)
    {
        if ($request->getMethod() == 'POST')
        {
            $task = new Task();
            $form = $this->createForm(new TaskType(), $task, array('action' => $this->generateUrl('todo_new')));
            $form->handleRequest($request);
            if ($form->isValid())
            {
                $task = $form->get('task')->getData();
                $due = $form->get('due')->getData();
                $data = $form->getData();
                echo '<pre>'; print_r($data);
                return new Response("Well done: $task - $due");
            }
            else
            {
                return $this->render('SeHirBundle:Default:todo.html.twig',
                            array('page' => 'Todo', 'form' => $form->createView()));
            }
        }
        else
        {
            return new Response('Only POST method accepted');
        }
    }
}

错误冒泡true是将所有错误组合在一起的。

错误弹出是基于你的浏览器。我不确定Symfony能关闭这种功能。

    required => false 

早该这么做了

技巧是将表单数据保存在会话中,并使用存储在同一会话中的数据填充表单类型,以防止表单提交失败。数据一直保存在会话中,直到成功提交表单。

完整的例子在这里:防止symfony应用程序中的"Confirm form resubmission"对话框

/**
 * @Route("/interest", service="my_test_bundle.controller.interest")
 */
class InterestController
{
    private $formFactory;
    private $router;
    public function __construct(
        FormFactoryInterface $formFactory,
        RouterInterface $router
    ) {
        $this->formFactory = $formFactory;
        $this->router = $router;
    }
    /**
     * @Method({"GET"})
     * @Route("", name="interest_index")
     * @Template()
     *
     * @param Request $request
     *
     * @return array
     */
    public function indexAction(Request $request)
    {
        $form = $this->createForm();
        $session = $request->getSession();
        if ($session->has($this->getFormName())) {
            $request->request->set(
                $this->getFormName(),
                unserialize($session->get($this->getFormName()))
            );
            $request->setMethod('POST');
            $form->handleRequest($request);
        }
        return ['interest_form' => $form->createView()];
    }
    /**
     * @Method({"POST"})
     * @Route("", name="interest_create")
     *
     * @param Request $request
     *
     * @return RedirectResponse
     */
    public function createAction(Request $request)
    {
        $session = $request->getSession();
        $form = $this->createForm();
        $form->handleRequest($request);
        if ($form->isValid()) {
            // Do something with: $form->getData();
            $session->remove($this->getFormName());
            $routeName = 'home_or_success_route';
        } else {
            $session->set(
                $this->getFormName(),
                serialize($request->request->get($this->getFormName()))
            );
            $routeName = 'interest_index';
        }
        return new RedirectResponse($this->router->generate($routeName));
    }
    private function createForm()
    {
        return $this->formFactory->create(
            InterestType::class,
            new Interest(),
            [
                'method' => 'POST',
                'action' => $this->router->generate('interest_create'),
                'attr' => ['id' => $this->getFormName()],
            ]
        );
    }
    private function getFormName()
    {
        return InterestType::NAME;
    }
}