web-dev-qa-db-fra.com

Symfony2, twig et JavaScript

Que dois-je faire pour que twig traite un fichier JavaScript? J'ai un fichier html.twig qui utilise une brindille JavaScript. Quelque chose comme ça:

{% extends 'BaseBundle::layout.html.twig' %}

{% block javascripts %}
    {{ parent() }}
    {% javascripts
        '@BaseBundle/Resources/js/main.js.twig'
    %}
    {% endjavascripts %}
{% endblock %}

< more template omitted >

Et des parties de main.js.twig:

function testFunction()
{
    alert('{{VariableFromPHP}}');
}

Et le contrôleur:

/**
 * @Route("/",name="home")
 * @Template("MyBundle:Default:index.html.twig")
 */
public function indexAction()
{
   return array( 'VariableFromPHP' => 'Hello World');
}

Je m'attendais à ce que le code JavaScript ressemble à ceci au moment de l'exécution: 

alert('Hello World');

Mais, le code est inchangé. Des idées que je fais mal?

Merci, Scott

13
Doo Dah

Assetic n'inclut pas les modèles de brindille; vous devez créer un contrôleur distinct pour le fichier javascript. Bien que je considère cela comme une mauvaise pratique en termes de performances, vous devrez traiter deux demandes de cette façon.

/**
 * @Route("/main.js")
 */
public function mainJsAction() {
    $params = array( 'test' => 'ok' );
    $rendered = $this->renderView( 'MyBundle:Default:main.js.twig', $params );
    $response = new \Symfony\Component\HttpFoundation\Response( $rendered );
    $response->headers->set( 'Content-Type', 'text/javascript' );
    return $response;
}
{% extends 'BaseBundle::layout.html.twig' %}

{% block javascripts %}
    {{ parent() }}
    <script type="text/javascript" src="{{ path('my_default_mainjs') }}"></script>
{% endblock %}

Une alternative consiste à vider les variables dynamiques dans le code HTML et à n’utiliser que des fichiers javascript statiques.

12
Zsolt Gyöngyösi

Ma suggestion d'utiliser des variables globales:

{% javascripts '@AcmeBundle/Resources/public/js/*' output='js/compiled/main.js'%}
        <script>
            var TWIG = {};
            TWIG.variableOne   = "{{ path('rote_to_nowhere') }}";
            TWIG.variableTwo   = "{{ helloworldVar }}";
            TWIG.variableThree = "{{ "something"|trans }}";
        </script>
        <script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}

alors vous pouvez l'utiliser dans votre fichier js:

alert(TWIG.variableTwo);
18
pleerock

Au lieu de cela, ce que j'ai fait est la suivante dans le fichier main.js:

function doGetStringFromSubClass()
{
    if (typeof getStringFromSubClass == 'function')
    {
        return getStringFromSubClass();
    }
    else
    {
        alert('getStringFromSubClass() needs to be defined.')
    }
}

function testFunction()
{
    alert(doGetStringFromSubClass());
}

et, dans les brindilles de la sous-classe, nous avons ceci main.js:

function getStringFromSubClass(){
    return "baseClassString";
    }

Et cette brindille:

{% extends 'BaseBundle:Default:index.html.twig' %}

{% block javascripts %}
    {{ parent() }}

    {% javascripts
        '@SomeSubclassBundle/Resources/js/main.js'
    %}

    <script type="text/javascript" src="{{ asset_url }}"></script>
    {% endjavascripts %}
{% endblock %}

Un peu maladroit, mais ça marche.

Scott

1
Doo Dah