the issue here is that i have both index and c as the evaluated expressions, after index[1] is evaluated, it will serve as a parameter to the userDetails. Hence, an e.g. like c.firstname.
<#ftl encoding='UTF-8'>
<#list param?chunk(3) as index>
<#list userDetails as c>
${c.index[1]}
</#list>
</#list>
However, i am assuming that Freemarker is evaluating all the expressions at one time, hence when this piece of code is being run, index[1] is not evaluated yet. Thus, i'm getting this error instead.
FreeMarker template error:
The following has evaluated to null or missing:
==> c.index [in template "src/template_fixedlength.ftl" at line 5, column 19]
Does anyone of you know of any workaround for this problem?
Thanks in advance!
The evaluation happens left to right in this case, like if it was (c.index)[1]. This is like so in pretty much all other languages too. If I understand well, index[1] would evaluate to the string "firstname", and you want c.firstname in effect. Then, the syntax is c[index[1]].
Related
I am learning ftl and have problem with variables.
I have an element a which has its own subelement b.
I access the subelement with the following method:
a.getChild("b")
Now, I check whether a subelement has content in the following way:
<#if a.getChild("b").getData()?has_content>
and this works as expected.
Now, I wanted to shorten this if's syntax by doing the following:
<#assign b>${a.getChild("b")}</#assign>
<#if b.getData()?has_content>
However, this produces error:
For "." left-hand operand: Expected a hash, but this has evaluated to a string
What am I doing wrong and how do I eliminate the need for calling the getChild in ifs?
I have hundreds of ifs in my production environment which all use getChild, sometimes even multiple times if subelements are nested so it would be great if I could shorten the syntax by assigning a child element to a variable.
I just started learning ftl yesterday, so this might be stupid question, sorry.
Simply do <#assign b = a.getChild("b")>.
With ${a.getChild("b")} you've outputted a string which then was assigned.
See the documentation also: https://freemarker.apache.org/docs/ref_directive_assign.html
I'm trying to make a function or macro to test a variable against all Freemarker is_xxxx types (https://freemarker.apache.org/docs/ref_builtins_expert.html#ref_builtin_isType), so that I can just run a variable through that function/macro to see what it is.
I could obviously just run each one at a time and return that, i.e.,
is_string? ${var?is_string?c} <br/>
is_hash? ${var?is_hash?c} <br/>
I was hoping to avoid that by <#list> ing through a hash, but I couldn't figure it out ... then I just got curious if this sort of thing were even possible.
At a loss how to do this, or if I can.
For example
<#assign builtIns = {"is_string":"is_string","is_number":"is_number","is_boolean":"is_boolean","is_date_like":"is_date_like","is_date_only":"is_date_only","is_time time":"is_time time",
"is_datetime":"is_datetime","is_unknown_date_like":"is_unknown_date_like","is_method":"is_method","is_transform":"is_transform","is_macro":"is_macro","is_hash hash":"is_hash hash","is_hash_ex":"is_hash_ex","is_sequence
sequence":"is_sequence sequence","is_collection":"is_collection","is_collection_ex":"is_collection_ex","is_enumerable":"is_enumerable","is_indexable":"is_indexable","is_directive":"is_directive","is_node
node":"is_node node","is_markup_output":"is_markup_output"}
/>
<#list builtIns as key,val>
${key},${val?val} <br/> // or something like this.
</#list>
Make sense? Possible? A different way to do this entirely?
Thanks!
No, the so called built-ins (things after the ?) has no value, so you can't put them into variables. That's unlike normal methods, FTL macros, and FTL functions, which can be passed around as a value. The difference is because some built-ins affect template parsing (kind of like compilation), so they are not purely runtime.
Well, you could get around that with generating the expression as a string then do myExpressionString?eval, but that's awkward and somewhat slow.
I have objects and want to check if a certain property exists.
I have nested maps and lists that look like this:
some.videos.files (map including a map including a list)
some always exists but may be empty.
If I do this:
<#if some.videos.files?has_content>
and some.videos doesn't exist I get an error.
So I do this now:
<#if some.videos?has_content && some.videos.files?has_content>
Is there a more elegant way to do this?
I know I could do
<#if some.videos?? && some.videos.files?has_content>
but I don't consider this to be much better especially if you may have deeper nested variables.
Basically I only want to know if some.videos.files exists and is not empty.
Yes, (some.videos.files)?has_content. The same logic works with ?? and ! too, like (some.videos.files)?? and (some.videos.files)![].
I just wonder if there is any simple and convinient way of handling possible null values in intermediate object in an expresssion:
request.service.contact.phone
I tried to surround it with (), but it did not work, when for example contact was null:
InvalidReferenceException: The following has evaluated to null or missing:
(request.service.contact.phone)!
I tried to escape each object, but FM thought that following expression part is builtin
ParseException: Unknown built-in variable: phone
request.service!.contact!.phone!
I will need to add conditionals but I do not like multiple if nesting. Is there something smarter?
I have a list structure called "stack".
At the point in my program which is causing problems, this is what stack holds:
stack([[s]],[np,[noun,john]])
I got this from running a trace, and its what stack is supposed to be holding.
When writing the next rule which is supposed to match this.
if
buffer([[Word|_]])
and aux(Word)
and stack([s],[np,[noun, john]])
If I do this then the rule executes as its supposed to. But I need to use a variable here instead of using "and stack([[s]],[np,[noun,john]])". However when I try to use anything else, the rule does not fire. I can't work out why. Other rules work fine when I use variables in the list.
Ive tried
stack([s]|Foo)
stack([s]|[Foo])
stack([MyHead]|[MyTail]... and literally every other combination I can think of.
I'm not entirely sure what is causing this problem
Your stack seems to have arity 2, where each arg is a list.
These aren't valid syntax for lists
stack([s]|Foo)
stack([s]|[Foo])
...
but since some Prolog declare the (|)/2 operator as alternative to (;)/2 (i.e. disjunction), you will not see any syntax error.
To understand you problem, you could try to unify, by mean of unification operator (=)/2
?- stack(S, Foo) = stack([[s]],[np,[noun,john]]).
you will get
S = [[s]]
Foo = [np,[noun,john]]