Symfony 2 custom form field type: how to add javascript and css only once?
forms, symfony, twig
Solution
I had to write a self contained form widget that requires javascript, I was able to achieve what you are trying to do through the `event_dispatcher` listening on the `kernel.response` to append the javascript at the end of the `Symfony\Component\HttpFoundation\Response`. Here's a snippet of my form type :
<?php
namespace AcmeBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
class AcmeFileType extends AbstractType{
private $twig;
private $dispatcher;
public function __construct(\Twig_Environment $twig, EventDispatcherInterface $dispatcher){
$this->twig = $twig;
$this->dispatcher = $dispatcher;
}
public function buildView(FormView $view, FormInterface $form, array $options){
$javascriptContent = $this->twig->render('AcmeBundle:Form:AcmeFileType.js.twig', array());
$this->dispatcher->addListener('kernel.response', function($event) use ($javascriptContent) {
$response = $event->getResponse();
$content = $response->getContent();
// finding position of </body> tag to add content before the end of the tag
$pos = strripos($content, '</body>');
$content = substr($content, 0, $pos).$javascriptContent.substr($content, $pos);
$response->setContent($content);
$event->setResponse($response);
});
}
...
When you define your form type in your services.yml it looks like this :
acme.form.acme_file_type:
class: AcmeBundle\Form\AcmeFileType
arguments:
- @twig
- @event_dispatcher
tags:
- { name: form.type, alias: acmefile }
So now, everytime you build a form with `acmefile` the javascript will be appended to the `<body>`. This solution does not prevent the javascript from being present multiple time though, but you should easily be able to improve this to suit your needs.
You can also play around with the `$response` object to modify the headers instead if you wish.
Problem
I want to use javascript in custom Symfony 2 form field type extension. So, I have Twig extension template like this: ``` {% block some_widget %} <input ... /> <script src="some.js"></script> <link href="some.css" /> {% endblock %} ``` But I want to have these script and link tags only once in my HTML, ideally in head tag, without modifing base template. I tried to extend Twig blocks, but I have no access to action template blocks inside form template. Or maybe something like this: ``` {# widget tempate #} {% block some_widget %} <input ... /> {{ use_javascript('some.js') }} {{ use_css('some.css') }} {% endblock %} {# main action template #} ... <head> {{ dump_javascripts() }} {{ dump_css() }} </head> ... ``` How to do this with Symfony 2 Forms + Twig? P.S. Sorry for my bad english.