Jonwd
Jonwd

Reputation: 655

How do I make my forms modular in Symfony?

I have 10 forms in a single page (they are in tabbed pages).

My controller function is massive, in an effort to make the forms modular, I was planning to just show the forms in my controller function and do the POST to their correspondent controller.

Some of these 10 forms are used in other pages, so by changing the action url, it makes it easier to manage them all in separate controllers.

But then, how am I going to show the form errors and prevent the form to reset if it was invalid?

I could achieve this if embedded controllers could redirect. Am I missing another option?

Symfony2 has to have a reason not to allow redirects in embedded controllers, but I wonder why.

Third edit:

Images of the actual forms: https://i.sstatic.net/IoJ3w.png

  1. Image 1: Step1 (can only be created once)
  2. Image 2: Step5 (can be created multiple times) You can see the create form and the edit form
  3. Image 3: Step5 ui forms are slided up.
  4. Image 4: Step6 same as Step1

These forms are not required to go in order, the user can create and save step6 without ever needing to create step1.

Second edit:

This isn't a multiple step form. I named them Step1, Step2, etc. for convenience.

Edit:

This is what I have:

class DefaultController extends Controller{
    public function processAction(){
        $request = $this->getRequest();
        /*** FORM 1 ****/
        $entity  = new Step1();
        $form1   = $this->createForm(new Step1Type(), $entity);
        if ($request->getMethod() == 'POST'){
            $form1->bindRequest($request);
            if($form1->isValid()){
                return $this->redirect($this->generateUrl('some_link'));
            }
        }
        /***/
        //Do the same for other forms

        return array(
            'form1'   => $form1->createView()
            //[...to form10]
        );
    }
}

This is what I would like to have: (I would do it with embedded controllers but you can't redirect)

class DefaultController extends Controller{
    public function processAction(){
        $request = $this->getRequest();
        /*** FORM 1 ****/
        $entity  = new Step1();
        $form1   = $this->createForm(new Step1Type(), $entity);
        //change $form1 action url to point to Step1Controller->createAction()
        /***/
        //Do the same for other forms

        return array(
            'form1'   => $form1->createView()
            //[...to form10]
        );
    }
}
class Step1Controller extends Controller{
    public function createAction(){
        $request = $this->getRequest();

        $entity  = new Step1();
        $form   = $this->createForm(new Step1Type(), $entity);

        $form->bindRequest($request);
        if($form->isValid()){
            //save entity
            return $this->redirect($this->generateUrl($getRedirectLinkFromForm));
        }
        return $this->redirect($this->generateUrl('some_other_link')); 
    }
}

Upvotes: 1

Views: 219

Answers (1)

Jonwd
Jonwd

Reputation: 655

I came up with 4 solutions that I could think of, in order from best to worst:

  1. AJAX
  2. No redirect in embedded controllers
  3. Save in session posted data / form errors in case form is not valid
  4. Modify Symfony2 internals to allow redirect from an embedded controller

AJAX

This is actually the best as it reduces whole page requests and it's highly modular.

You would render all 10 embedded controllers but each submit button will instead do an ajax post pointed to the correspondant controller, which will only process the correspondent forms and it will only return the view of that specific form.

And you don't need to get fancy on your javascript, as you only need to make the AJAX call when submit is clicked and load the response to the div where the form is.


No redirect in embedded controllers

The problem with this is that if the user presses F5, it will resend the POST data.


Save in session posted data / form errors in case form is not valid

and Modify Symfony2 internals to allow redirect from an embedded controller

These 2 options are less desirable as it creates complexity.

Upvotes: 1

Related Questions