I have the issue related to string formatting in a function of the freemarker. Let's admit there is the next function:
<#function transformWithSign sign amount>
<#--<#local str = amount?string["########.00"]>-->
<#local str = amount?string>
<#local str += sign?string>
<#return str>
</#function>
So, the commented out line does not work and appears the error is "freemarker.core.NonMethodException: For "...(...)" callee: Expected a method or function, but this has evaluated to a string (wrapper: f.t.SimpleScalar):
==> amount?string [in template "html/invoiceTemplate.ftlh" at line 52, column 23]"
This row works fine:
<#local str = amount?string>
What is wrong there? Or does the freemarker function not work with string formatting?
The problem is that amount is not a number, but a string that looks like a number. Thus, amount?string will just return the original string as is, and that string doesn't support the [] or () operators. If amount was a number (or date, or boolean), then ?string returns a more fancy string that does support those operators.
To demonstrate the problem:
<#assign amount = 123>
<#-- Works: -->
${amount?string}
<#-- Also works: -->
${amount?string["########.00"]}
But (note the quotation marks around 123):
<#assign amount = "123">
<#-- Works: -->
${amount?string}
<#-- FAILS: -->
${amount?string["########.00"]}
Ideally, you should ensure that amount comes as a number. But, you can also ask FreeMarker to convert it if it's a string, although, be sure that the string in amount uses the typical computer language number format (not some localized format):
${amount?number?string["########.00"]}
Related
I need to check if the last number of character of a ${string} is equal to 9.
The string or numbers that I have to handle with is something 831, 519 or 1351.
However I dont know how do do it properly. I tried already something like:
${string?replace((string.length)-1,"9")}
At the end there should be instead of 831 --> 839 or 1351 --> 1359 and so on.
Any sugestions about how I can archive this ?
Oh and by the way. If I use the fuction above this error massage comes up:
Script error: You have used ?number on a string-value which is not a number (or is empty or contains spaces).
And what I tried also was:
code snippet
Because the original number is somethink like 831.896.
You could use string slicing to keep all characters except for the last one like this:
<#assign string = "1234">
<#assign string = string[0..<string?length-1] + "9">
${string}
Results in:
1239
Since you want to replace that thing, use ?replace. This replaces the last character with 9, if the last character is a digit that's not already 9:
${s?replace("[0-8]$", '9', 'r')}
How to print only 5 line of each having 32 chars using Freemarker. Currently i have the below solution. Is there any better way of doing using split or substring
<#assign msg="Tell FreeMarker to convert string to real date-time value Convert date-time value to date-only value Let FreeMarker format it according the date_format setting">
<#assign len=msg?length>
<#list 1..5 as i>
<#assign start=(i-1)*32>
<#assign end=i*32>
<#if (end <len)>
${msg[start..end]}
<#else>
${msg[start..len-1]}
</#if>
</#list>
result is
Tell FreeMarker to convert string
g to real date-time value Convert
t date-time value to date-only va
alue Let FreeMarker format it acc
cording the date_format setting
Like this:
<#list msg?matches(".{1,32}")[0..*5] as row>
${row}
</#list>
Note that the "length limited range" operator, ..*, doesn't give error if the length is less than what you asked for. So even with your approach, you can remove the end assignment and the #if/#else, and just use ${msg[start..*32]}.
If I do
template_string = "class=btn submit-button %<additional_classes>"
format(template_string, additional_classes: 'some-class')
it works. However, if I do
template_string = "class='btn submit-button %<additional_classes>'"
format(template_string, additional_classes: 'some-class')
it fails, giving
ArgumentError:
malformed format string - %'
(Notice the quotation marks surrounding the classes in the second template_string - this is the only difference between the two blocks of Ruby code). How do I make it work? In other words, how do I produce the following?
class='btn submit-button some-class'
I don't believe that I can just use interpolation, because sometimes I need to pass in other variables. In other words, I can't do
additional_classes = 'some-class'
"class='btn submit-button #{additional_classes}'"
because sometimes I want to reuse the same string "template" but pass in other variables, to produce strings such as the following:
class='btn submit-button some-other-class'
or
class='btn submit-button some-third-class'
From the fine manual:
format(format_string [, arguments...] ) → string
[...]
For more complex formatting, Ruby supports a reference by name. %<name>s style uses format style, but %{name} style doesn't.
The documentation isn't as clear as it could be but when you use the %<...> form, it is expecting to see %<name>s where name is the hash key and s is the format type: s for string, d for number, ... If you say:
%<additional_classes>'
then format will try to interpret ' as a type when there is no such type specifier so you get an ArgumentError because the format string is malformed.
You probably want to use the %{...} form instead:
template_string = "class='btn submit-button %{additional_classes}'"
#--------------------------------------------^------------------^
Your format string is missing the field type specifier. The field type specifier is mandatory in a format string.
It is not clear to me why the first example does not raise an error, since the mandatory field type specifier is missing. It could be a bug, or I am completely misreading the documentation.
However, it is not clear to me why you consider this example to work:
template_string = "class=btn submit-button %<additional_classes>"
format(template_string, additional_classes: 'some-class')
#=> 'class=btn submit-button %'
# ↑
As you can see, the % is not interpreted as the part of a format string but as a literal %. I would consider this a bug, it should raise an error, just like the second example does.
In the second example, you can clearly see the problem:
ArgumentError: malformed format string - %'
↑
Since a format string must have a field type specifier, and the only character after the % (except the field name) is ', this is interpreted as the field type specifier. And since ' is not a legal field type, format raises an error in which it explicitly tells you that it interpreted the ' as part of the format string.
Since you want to format strings, you should use the s (string) field type specifier:
template_string = "class=btn 'submit-button %<additional_classes>s'"
# ↑
format(template_string, additional_classes: 'some-class')
#=> "class=btn 'submit-button some-class'"
# ↑↑↑↑↑↑↑↑↑↑↑
Alternatively, you can use the %{} form:
template_string = "class=btn 'submit-button %{additional_classes}'"
# ↑ ↑
format(template_string, additional_classes: 'some-class')
#=> "class=btn 'submit-button some-class'"
# ↑↑↑↑↑↑↑↑↑↑↑
I want to convert a string to number in freemarker. I want to put some conditional check based on the value of the number. ?number doesn't seems to work.
Any suggestions?
Sorry, ?number does work fine. I was not able to compare the converted number with another number.
This didn't work for me:
<#assign num = numString?number>
<#if num > 100>
</#if>
When I enclosed (num > 100) inside the brackets it worked:
<#if (num > 100)>
</#if>
Since the comparison was not working, I was assuming that conversion was not happening.
My bad.
In your code, you use the closed bracket, so freemarker is evaluating
<#if num >
you should instead use
<#if num gt 100>
This is discussed at the end of this documentation on if statements
https://freemarker.apache.org/docs/ref_directive_if.html
The reason this is working for some and not others is because of the parentheses, which is also explained at the bottom of the documentation
I think you can use it like this:string?eval
Use the below code
<#if num?string > 100?string>
</#if>
It worked for me.
I'm trying to output prettier numbers from my FreeMarker template in GeoServer:
<#list features as feature>
<#if attribute.name="lon" || attribute.name="lat">
<td>${feature[attribute.name].value?round}</td>
<#else>
<td>${feature[attribute.name].value}</td>
</#if>
</#list>
If I take out the ?round, I get things like "-121.469166666667". I simply wish to format that number a bit, say by rounding it to 4 decimal places.
I've tried a couple things:
${feature[attribute.name].value?number}
${(feature[attribute.name].value)?number.string("0.0000")}
But those complain of "Expected hash.", so I'm feeling like it's just a syntax issue of conveying the string in the hash to the ? operator correctly, so that I'm actually executing methods on the string... but that has stumped me.
If you always want 4 decimals:
${feature[attribute.name].value?string("0.0000")}
If you want at most 4 decimals, then ?string("0.####")
The ?number part is only needed if value is a string. In that case you should write [...].value?number?string("0.0000"). There's no such thing as ?number.string, hence the "expected hash" error message.