Inject Twig into JS with Assetic (.js.twig power)
Web agency » Digital news » Inject Twig into JS with Assetic (.js.twig power)

Inject Twig into JS with Assetic (.js.twig power)

First, this article is a minute report hack which I made a few days ago.

Not being a strong advocate ofAssetic, it is mandatory for me to use it on the projects that we are currently developing in my company. And therefore, the use of Assetic must render me a maximum service, like all tools.

A problem ? A solution !

Here is my problem. We've all had the need to build a route in a JS file. To this problem, we have all found a pseudo-solution.

  1. You inject into your page (HTML) a JS variable with content Twig. This variable will be used in a JavaScript file loaded via Assetic. Effective but difficult to read and not very user-friendly.
    1
    2
    3
    4
    5
    6
    7
    8
    // branch template
    <script>
    var myVar = « {{ path(‘my_route’) }}";
    </script>
    // javascript file
    $("#sort").on("change", function() {
    window.location.href = myVar + $(this).val();
  2. You are using FOSJsRoutingBundle and you are using a catalog of routes in a file JS generated by the bundle. Advantage, routes can be generated very easily, with context-related parameters. Disadvantage, the use of a bundle additional, and the obligation to declare the roads usable with the option expose=true. This can potentially expose some routes in the file containing all exposed routes.
    Sometimes the use of FOSJsRoutingBundle is a bit like using a bazooka to kill a fly: it costs a lot when you don't need to do much. The alternative, trying to inject Twig in his JS.

In which case of use, and what are the limits?

Be careful, this hack should not be used at all costs as its use is very limited.

Assetic compiles JavaScript files in a way completely detached from the current context. I mean context by current request. If in the file JS you can try to use anything and everything, when generating the file, only certain variables will be available.

  • The global variables of Twig
  • functions and filters Twig can be used
  • Routes are available and can be generated
    CORN !! context is not available, so didn't expect to use current request parameters, via variables Twig In any case.

You can therefore generate routes without dynamic parameters or with static parameters, or even use global parameters such as those injected into the parameter.yml.

All about how to set it up

You need to create a filter Twig so that Assetic know what to do with your files. You can place it in src/AppBundle/Filter.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
namespace AppBundleFilter;
use AsseticAssetAssetInterface;
use AsseticFilterFilterInterface;
use symfonyBundleTwigBundleTwigEngine;
/ **
* @author Baptist Donaux@ gmail.com>
*/
class TwigFilter implements FilterInterface
{
private $template;
public insurance function __construct(TwigEngine $templating)
{
$ this->templating = $templating;
}
public insurance function filterLoad(AssetInterface $asset)
{}
public insurance function filterDump(AssetInterface $asset)
{
$content = $asset->getContent();
$content = $ this->templating->render($asset->getSourceRoot()."/".$asset->getSourcePath());
$asset->setContent($content);
}
}

You must declare this filter. This is a service that we will tag as being a filter ofAssetic. You can declare it in app/config/services.yml.

1
2
3
4
5
6
7
services:
assetic.filter.twig:
class: AppBundleFilterTwigFilter
arguments:
- @template
tags:
- {name: “assetic.filter”, a.k.a: “twig” }

In your template where you want to use a file like .js.twig, you will simply declare the filter Assetic.

1
2
3
4
5
{% javascripts filter=”twig”
'@AppBundle/Resources/public/js/file.js.twig'
%}
<script type=“text/javascript” src=« {{ asset_url }}« ></script>
{% endjavascripts %}

here is the file file.js.twig used in my case.

1
2
3
$(" #spell ").we("change", function() {
window.location.href= "{{ path('my_route', {}) }}" + $(this).val();
});

Once the file is generated here is the rendering.

1
2
3
$(" #spell ").we("change", function() {
window.location.href= “/my_route” + $(this).val();
});

Conclusion, why not?

The use of this trick must be really measured because if it allows to inject a few variables or a few simple routes, the problems can quickly be more important. In these cases, this solution may not be enough.

This solution also aims to show thatAssetic can propose solutions to problems, solutions that Grunt, Gulp ou Brunch can't always offer.

★ ★ ★ ★ ★