Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send javascripts to the bottom? (in symfony 2)

I want to create views that can by themselves print some html code, and at the same time, send javascript code to the bottom, without extending the layout

The idea is that I have a layout, then the specific view for the current url extends that layout, and inside that view, I include other views, which have the power of adding code to other blocks that are out of scope (because they don't inherit from the layout or the view that inherits from it). Is that possible?

Suppose this is a part of my layout:

{# ::layout.html.twig #}
.
.
{% block javascripts %}
{% endblock %}
</body>
.
.

and this is my view:

{# Company:Bundle:about.html.twig #}
{% extends '::layout.html.twig' %}
.
.
{% include 'Company:buttons:google_button.html.twig' %}
.
.

And this is the view I want to include, for example, a google +1 button:

{# Company:buttons:google_button.html.twig #}
<gb></gb> {# or whatever #}

{# somehow send '<script>blabla</script>' to the 'javascripts' block #}

Is it possible to do something like this with twig and symfony2?

like image 935
HappyDeveloper Avatar asked Jun 30 '11 12:06

HappyDeveloper


3 Answers

I guess you'll have to write your own Twig extension that will define two functions, let's say add_js and print_js.

Twig Extension:

namespace Me\MyBundle\Twig\Extension;

class MyExtension extends \Twig_Extension {
    private $js = array();

    /**
     * {@inheritdoc}
     */
    public function getFunctions() {
        return array(
            'put_js' => new \Twig_Function_Method($this, 'putJs', array('is_safe' => array('html'))),
            'print_js' => new \Twig_Function_Method($this, 'printJs', array('is_safe' => array('html')))
        );
    }

    public function putJs($js) {
        $this->js[] = $js;
    }

    public function printJs() {
        return implode(PHP_EOL, $this->js);
    }

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName() {
        return 'my';
    }
}

Dependency injection configuration:

<service id="twig.extension.me.my" class="Me\MyBundle\Twig\Extension\MyExtension" public="false">
    <tag name="twig.extension" />
</service>

Final usage:

{# ::layout.html.twig #}

   ...
   {{ print_js() }}
</body>

{# Company:buttons:google_button.html.twig #}

{% put_js('<script>...</script>') %}
like image 182
Crozin Avatar answered Nov 20 '22 01:11

Crozin


just wanted to implement a bundle containing the code from @Crozin but on packagist.org i found a already finished bundle:

Asset Managment Bundle

like image 45
c33s Avatar answered Nov 20 '22 00:11

c33s


I have just implemented the exact problem you are facing using 'Use': http://twig.sensiolabs.org/doc/tags/use.html

Some refactoring will be needed as you will need to remove the javascript block from your main base file and include it again in a javascript twig file. Then inside your view, you can access the javascript block by first defining:

{% use 'ExampleBundle::javascript.html.twig' with javascript' %}

like image 1
Elliot Coad Avatar answered Nov 20 '22 01:11

Elliot Coad