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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With