Reputation: 1220
I have the following freemarker template:
[#local snippet ][#noparse]
[#assign out ]value: ${v}
[/#assign]
[/#noparse]
[/#local]
[#assign hook = snippet?interpret ]
...
[#macro trigger ]
[@hook /]
[/#macro]
...
[#list values as v ]
[@trigger ]
[/#list]
${out}
What it essentially does is defining a hooks to execute at a certain later moment and a macro to trigger it's execution.
When I try to render this template, i get the following error:
The following has evaluated to null or missing:
==> v [in template "xxx.ftl->anonymous_interpreted" at line 1, column 17]
It might be interesting to note that the following:
[#list values as v ]
[@hook ]
[/#list]
is just working, i.e. rendering the template as I would expect, printing value: xxx
for each value in the list.
I just discovered that the error doesn't occur if instead of an interpreted snippet I pass a regular macro:
[#assign hook = myMacro ]
...
but not if the macro is defined in another namespace.
Upvotes: 1
Views: 1333
Reputation: 31112
A loop variable (v
) is basically a local variable of the #list
block. So, with Java-ish pseudo-code what you try to do is like:
void main() {
for (int v : values) {
trigger();
}
}
void trigger() {
print(v); // Error, v is not visible here!
}
As of calling a directive defined with ?interpret
, that's special, as it tries to behave as if you have copy-pasted the code snippet at the place of invocation. That is, the directive that you call with @hook
doesn't create its own local context. So that's why it sees v
if you call it directly from the loop. But if you call it form trigger
, then it will live in the local context of the trigger
macro, which do have its own local context.
As of making it work... one possibility is assigning v
to a namespace-scope variable via <#assign value = v>
, and then refer to value
in the interpreted fragment. Another solution is of course getting rid of the trigger
indirection, if you can. Yet another solution is to define trigger
with ?interpret
instead of with #macro
, because then trigger
will see v
, and so hook
will too.
Upvotes: 3