BentCoder BentCoder - 1 month ago 5
PHP Question

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

When form submission fails, same webform is presented to user with the error messages which is fine however, when they hit F5 or use back/forward buttons of browser, "Confirm re-submission" popup appears. How can prevent this action?

Note: I used to use redirection method in CodeIgniter without losing error messages but I don't know how to handle same kind of process in Symfony since I'm new to it. Any solution is acceptable though.

Controller:

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');
}
}
}

Answer

Trick is to keep form data in a session and populate form type with the data stored in same session for failing forms submissions. Data stays in session until successful form submission.

Full example is here: Preventing 'Confirm form resubmission' dialog in symfony applications

/**
 * @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;
    }
}
Comments