Nunjucks: Impossible to put a macro accessing global scope in an other file ?

Created on 20 Sep 2015  路  3Comments  路  Source: mozilla/nunjucks

Hello guys !

In my app.js, I have this :app.locals.testvalue = "lolo"

In my macro.html, I have this :
{% macro powertestvalue(x) %}
{{ x }} : {{ testvalue }}
{% endmacro %}

The problem is that I can only user the powertestvalue macro in "macro.html" because of the following :

  1. If I use "include", I won't be able to use the powertestvalue from the file which includes macro.html .
  2. If I use "import", macro.html won't access the global scope, and won't be able to use {{ testvalue }}.

Is this a bug ?

( It's even worse than expected. Let's say I want to make a superclass from which my layouts will inherits, because include and import don't work for what I want. Well, I can't : I can access a macro which is defined in the parent, but not in the parent of the parent. So I think it's a bug)

Most helpful comment

this is definitely a bug. I have the same problem.

I had a template dedicated solely to exporting a set of specific macros. It worked fine until I added i18n methods to my environment. now I can't use i18n methods in these macros, if I import them, because imports can't see the context and by including this dedicated template I have no access to the macros stored in there. sending all these i18n (I have like 6 of them) methods as arguments for every single macro (9 right now and growing) every time for every call... its beyond stupid and assigning the methods to env.addGlobal is also not an option, since these methods have to be assigned to every render session explicitly since every session has its own locale assigned.

All 3 comments

This is not a bug, it is working as expected. Context variables are not globals. Context variables are accessible in the rendered template only; if you want them accessible within a macro, pass them in as an argument. If you want a true global that is accessible everywhere, use env.addGlobal.

IMO the fact that you can access context vars from within a macro that is defined directly in the rendered template is a bit odd, and I generally don't make use of it. I can see a defense for it, though -- the macro is defined within the rendering context. In any case, those are the semantics nunjucks inherited from Jinja, and they aren't going to change.

I'm not sure I understand the last paragraph you added on about inheritance, but it sounds like a separate issue. If you think it's a bug, please open a new issue for it with a clearer description of the problem.

this is definitely a bug. I have the same problem.

I had a template dedicated solely to exporting a set of specific macros. It worked fine until I added i18n methods to my environment. now I can't use i18n methods in these macros, if I import them, because imports can't see the context and by including this dedicated template I have no access to the macros stored in there. sending all these i18n (I have like 6 of them) methods as arguments for every single macro (9 right now and growing) every time for every call... its beyond stupid and assigning the methods to env.addGlobal is also not an option, since these methods have to be assigned to every render session explicitly since every session has its own locale assigned.

You have lots of options:

  1. Make these methods of a single object in context, so you're only talking about a single object to pass around, not six separate functions.
  2. Use a separate env for each "render session".
  3. Use the same env, and add the i18n methods via env.addGlobal, but make the methods refer to some other global / thread-local context for the current locale. (Hard to be more specific about this option without knowing the details of the context you're rendering from.)

The semantics of context var accessibility in macros matches Jinja2 and there is zero chance that it will change in nunjucks. Part of the purpose of macros is encapsulation, so you know that the macro depends only on explicitly-configured globals and its arguments, not also implicitly on whatever context data happens to be passed in to the render.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gaboesquivel picture gaboesquivel  路  4Comments

ricordisamoa picture ricordisamoa  路  5Comments

felipenmoura picture felipenmoura  路  7Comments

boutell picture boutell  路  6Comments

atian25 picture atian25  路  5Comments