Extend twig-loader with custom functions

Viewed 648

I'm using twig-loader package within a Symfony 5 application that runs Encore (webpack). While trying to load a template via the twig-loader, I would like to extend the twig.js-functionality (which is used by the loader package).

So, basically, I need this to run:

// webpack.config.js
Encore.
  ...
  .addLoader({
      test: /\.twig$/,
      loader: 'twig-loader',
  })
  ...
;

module.exports = Encore.getWebpackConfig();


// somewhere in my js-file
const template = require('./form.html.twig');
template({
  'label': 'Some label',
});


// And the twig-file:
<form method="post" action="{{ path('example_route', {'some': 'parameter'}) }}">
    <button>{{ label }}</button>
</form>

The error I get, when rendering the above is, that the path-function is not known by twig.js:

Twig.Error {message: "path function does not exist and is not defined in the context", name: "TwigException", type: "TwigException", file: "$resolved:3132…b7d2:form.html.twig"}

Is there any way, I can extend the twig.js functionality globally, so that twig-loader uses my extended twig.js package?

1 Answers

Since the templates populated at runtime on the browser, and the path() function in twig is a server-side function (from the Router component), path won't work as you expect.

Since your path is static, though, there's an easy solution: pass it to the template as a variable, passing it from server-side twig, e.g.

<div id='my_data' data-example-path='{{ path('example_route') }}'></div>

If you use stimulus, even better, you can pass it to the controller as a variable.

If you need dynamic paths, use fosjsrouting bundle (https://github.com/FriendsOfSymfony/FOSJsRoutingBundle), then create the path in your js file, then pass that route to the twig renderer as before.

There's no way to implement path() in twig.js, because it doesn't have access to routing table.

Related