john
john

Reputation: 1280

Multiple Symfony Forms Added Accross Many Pages

I've created a new form type for a simple one field newsletter signup form. What's the best way to embed this across different pages, multiple times on my site?

I could create a new instance of this form with a different name in every controller to show in my twig templates, but this seems a little messy. Ideally I'd like to be able to add more than one form on a page, and add them easily to a template.

I've tried {% render controller('MyBundle:EmailSubscribe:subscribe') %} but this doesn't work with multiple inserts, and I'm sure there's a better way anyway. Any ideas?

Upvotes: 1

Views: 1328

Answers (3)

Theodore Enderby
Theodore Enderby

Reputation: 642

Im a fan of xurshid29's Answer

What I do is simplay render the controller like your answer suggests. But that causes only one form to get processed, and leaves the unprocessed forms with errors like Cannot extra fields and so forth.

The Solution:

Pass the request from the original controller.

In Controller

function myAction(Request $request){
    $this->render('path:to:template.html.twig', array('request'=>$request));
}

And In my Twig Template I simply pass the request to that controller.

{% render(controller('path:to:controller',{request:request} %}

And now you can create a base template for that form and include it in any template all across the site. This was especially useful for me with FOSUserBundle!

There may be some kind of twig function app.request ? I've been too lazy to try look it up. But in that case you don't have to pass request from original controller.


Extra tips on this subject

What I like to do that allows me to insert my forms anywhere for rapid dev is to build a controller/template for each form, like a "Join our Mailing List" or something.

Controller - The goal of this controller is to process the form and output "success" or show the form.

public function emailSubscribeFormAction(Request $request){
    $email = new Email() //Presumed Entity for form
    $form = /* Create Form Here */->getForm();
    $form->handleRequest($request);
    if($form->isValid()){
        $form = "success"; //Change form into a string
    }
    $this->render('path:to:email-form.html.twig', array(
        'form'=>($form=="success") ? $form : $form->createView();, // Either pass success or the form view
        'request'=>$request

}

Twig email-form.html.twig

{% if form == "success" %}
   <h4 id="form-success">Thanks for joining!</h4>
   <script>
       window.location = "#form-success" /*Bring the user back to the success message*/
   </script>
{% else %}
   <h4>Come on, Join Our Mailing List!</h4>
   {{ form(form) }}
{% endif %}

Now you can render that controller anywhere and not have to worry about another thing about it. Can work with multiple forms but I may have read there are drawbacks to rendering controllers like this?

Upvotes: 1

iiirxs
iiirxs

Reputation: 4582

If I understood your problem correctly you want to embed the same form multiple times in a page and this is to be done for multiple pages. So lets say that for page_1 you want to embed the subscribe_form N times you can obviously create a form and add this form type N times like this:

$form = $this->createFormBuilder()
        ->add('subscribe1',new SubscribeType())
        ->add('subscribe2',new SubscribeType())
        ... 
        ->add('subscribeN',new SubscribeType())
        ->getForm();

So you can also do this in a for loop like this:

$form = $this->createFormBuilder();
for ($i = 1; $i<N+1; $i++){
    $formName = 'subscribe'.$i;
    $form->add($formName,new SubscribeType());
}
$form->getForm();

Now you can include this code in a controller as you said and pass the variable N as argument in each of your twig templates. Moreover, you can do this through javascript especially if you want to add these forms(SubscribeType) dynamically using allow_add option in your form. Documentation about this is here: http://symfony.com/doc/current/cookbook/form/form_collections.html#allowing-new-tags-with-the-prototype.

Hope that helps otherwise inform me if I misunderstood your problem.

Upvotes: 0

xurshid29
xurshid29

Reputation: 4210

May be with Twig extension? This kind of task is the next one in my current project (e-commerce project where I need to display multiple addToCart forms on category pages), I'm also planning to do this with Twig function, for example (I did'nt test it yet):

private $formFactory;

public function __construct(FormFactoryInterface $formFactory)
{
    $this->formFactory = $formFactory;
}

public function getFunctions() {
    return [
        new \Twig_SimpleFunction('newsletter_form', [$this, 'getNewsletterForm']),
    ];
}

public function getNewsletterForm()
{
    $formFactory = $this->formFactory;
    $form = $formFactory->create('my_form_alias', null_OR_data);

    return $form->createView();
}

and use it in template as newsletter_form

Upvotes: 1

Related Questions