Access template model from a macro using parameter - freemarker

I have a form with input field (the example is simplified):
<input type="text" value="${model.person.age}">
This is working as expected and now I want to write a macro for this:
<#macro input path inputType="text">
<input type="${inputType}" value="${model[path]}">
</#macro>
that can be used with
<#lib.input "person.age" />
I found ${model[path]} solution here but it does not work in my case. I'm using Freemarker 2.3.21 and Spring MVC 4.1.0.

Can't you just pass in the value itself, like <#lib.input person.age>? Anyway, if you absolutely have to pass in that expression unevaluated, then in the macro you can use value="${path?eval}". It need not be a "path" of course, it can be any kind of expression. (model[path] doesn't work, since the value inside the [] meant to be a variable name, which can contain any characters, not some kind of path expression.)

Related

Issues with Parameters containg whitespaces

i've the following situation with Freemarker.
When returning to a page in .ftl i send from Java a parameter to the url, similar to "AAA% BBB#DDD.COM", in Java it is ok.
When looking at the Url it does instead Write : "AAA%25+BBB#DDD.COM" And then with the following code:
<#if myCase??>
value = ${user}
</#if>
It does write in my html field "AAA%" but not the remaining.
How can i try to solve this issue?
Thanks in advance.
EDIT: After further investigations i do see the code i put before does write this on the Html:
value="AAA%" BBB#CCC.com=""
EDIT2: Let'see if i can give you more informations, first of, here's the relevant Java code :
Map mapping = new HashMap();
if(user != null && !user.isEmpty()){
mapping.put("user",user); //EG: AAA% BBB#DDD.COM (Checked in debug)
}
I have an URL similar to : mysite.xx?user=AAA%25+BBB#DDD.COM so the user it's attached as query param of the url.
I do need to reuse the "user" param to repopulate the Form field relative to the username, this is not a valid email i know, but an alias system already installed by the customer does the aliasing system this way.
What could be the cause of the problem
Given your template:
<#if myCase??>
value = ${user}
</#if>
Output written by Freemarker in output-mode HTML results in following:
value = AAA% BBB#DDD.COM
Freemarker does not understand that (from your context) the value of user should be an attribute-value (assignment). Instead it treats the contents of string user as HTML itself (this could be complete HTML-source as input-field, single tags, etc.). It simply pastes the contents of the model at the position in your template where you have set the variable-interpolation ${user}.
The Freemarker-result is no valid HTML (attribute-value pair), because each attribute should adhere some naming-conventions (i.e. no special-characters). When the attribute has a value, it is followed by an equal-sign and this followed by the value enclosed in double-quotes.
So most browsers convert your result into a valid HTML attribute - actually two attributes: value="AAA%" and BBB#CCC.com="". Opened the output-HTML in Firefox, you will see this in Inspector (NOT IN the raw source-view):
<input type="text" value="AAA%" bbb#ddd.com="">
What is not the cause
FreeMarker is auto-escaping (escpecially when in OutputMode HTML) when it writes the final HTML.
#ddekany Thanks for your comment ! It made me reproduce and discover the real cause.
URL encoding/decoding
In Java you could even encode the string variable user. So it converts % (i.e. percent-sign followed by space) into %25+ which is valid to be used inside an URL.
Run this java snippet online on IDEONE to the effects of URL-encoding and URL-decoding.
Solutions
Use either of these solutions to get desired output by fixing the HTML-attribute value-assignment in your template:
(1) use double-quotes:
<#if myCase??>
value="${user}"
</#if>
(2) use some built-ins to transform the plain string-output:
Use some of FreeMarker's built-ins for strings. In your case you could append ?url to the variable-name and use double-quotes around your variable-interpolation within your template, e.g.:
<#if myCase??>
href="mailto:${user?url}"
</#if>
Caution: validate URL or email-address (even parts of it) as early as possible
BBB#DDD.COM is a valid email-address. But % and whitespaces are not allowed inside an email-address.
On the other side # is typically not part of an URL, except as part inside a query-param value. But your user (URL) does not start with http:// etc.
So depending on the use-case/purpose of your (so called URL) user with value AAA% BBB#DDD.COM it could finally represent part of an URL or email-address.
In your special case, said:
populate the form field relative to the username. Model-variable user does not contain a valid email-address. It is used in conjunction with an alias system already installed by the customer. So aliasing will work this way.
Let's suppose the end-user which does later edit the form-field is responsible of making it valid (or a script does this validation).
Anyway bear in mind that an internet-address (like URL/email) needs some validation:
either before written to the final HTML (using Java or Freemarker)
or after being further processed inside your web-page (using JavaScript).
Otherwise it could possibly not yield the desired effect.
See also
Related questions:
Is there any way to url decode variable on Freemarker?
Java URL encoding of query string parameters

Freemarker - dynamic name for user-defined directive invocation

I'm trying to port some old Apache Tiles stuff to Freemarker, and one of the things the tiles code does is pass around variables with the names of tiles (jsp files more or less). These variables decide at runtime which templates are transcluded into the current template.
I'm trying to figure out if there's a way to do that with Freemarker macros. Something like this:
<#macro mything>
test
</#macro>
<#macro myotherthing>
other
</#macro>
<#"my${which}thing" />
If which="other", then the result should be
other
If which="", then the result should be:
test
However, I get an error:
Syntax error in nameless template in line 9, column 12:
Encountered "}", but was expecting one of:
"."
".."
<DOT_DOT_LESS>
"..*"
"?"
"??"
"!"
","
":"
"["
"("
<TERMINATING_EXCLAM>
I'm guessing a user-defined directive invocation can't be an expression or something. I guess I can use the include directive instead, but is there any way to do this with macro invocation--dynamically pick the macro name to invoke at runtime?
Like this:
<#.vars["my${which}thing"] />
Explanation:
<#macro m>...</#macro> just assigns the macro (macros are values) to the variable m
In <#m />, the m part is interpreted as a usual expression. It happens to be a simple variable reference expression in this case, but it could be a more complex expression as well (parenthesis may be needed around it though).
Variables with dynamic name can be read through the reserved .vars hash, like .vars[nameExpression].

Handlebars triple stache inside of a double stache

I have registered a handlebars helper by the name of "t" that will translate a string. I have a Handlebars template which uses the value of a variable that will be a word:
{{{word}}}
I would like to translate the value of that variable using my helper, but cannot do
{{t "{{{word}}}" }} or {{t {{{word}}} }}
I am inexperienced with Handlebars and am wondering - What is the simplest way to achieve this?
{{t word}}
Simply pass the reference into your helper without brackets.
You only need brackets for outputting the value of the reference to the page:
Handlebars HTML-escapes values returned by a {{expression}}. If you
don't want Handlebars to escape a value, use the "triple-stash", {{{.
UPDATE:
If you need to perform some kind of operation (such as escaping HTML) on the value of word, you can make a second helper and pass that into your first helper using ( parentheses ):
{{t (myOtherHelper word)}}

How to output ${expression} in FreeMarker that contains HTML AS HTML

In my data model myVar contains <b>hello</b> and when I bring it like this ${myVar} the output I get is literally <b>hello</b> rather than hello.
Any idea how to correct this?
Certainly you have HTML escaping on, so try <#noescape>${myvar}</#noescape>.
Update: Since 2.3.24 a new kind of auto-escaping was introduced, which doesn't use #escape, and hence nor #noescape. When that's used, write ${myvar?no_esc} to avoid escaping. Or, you can put the value into the data-model already as a TemplateHTMLOutputModel (created with HTMLOutputFormat.fromMarkup(myString)), and then FreeMarker will know without ?no_esc that it need not be escaped.

ruby watir web-driver can't access dynamic elements

I have a site I need to login to but one of the input text fields id and name change each time. Is there a way to access element via a regex? Thanks in advance.
Example:
id="form:wrap:j_idt1297:0:j_idt1298:input"
id="form:wrap:j_idt2151:0:j_idt2152:input"
<input class="iceInpSecrt large"
id="form:wrap:j_idt1297:0:j_idt1298:input"
name="form:wrap:j_idt1297:0:j_idt1298:input"
onblur="setFocus('');" onfocus="setFocus(this.id);"
onkeyup="iceSubmit(form,this,event);"
onmousedown="this.focus();" tabindex="" type="password" value="">
Yes, you can match elements using regular expressions. It is similar to locating the id/name by string.
It looks like:
browser.text_field(:id => /a_regex/)
For your example, the following would locate the text field with either of the ids mentioned:
browser.text_field(:id => /form:wrap:j_idt\d{4}:0:j_idt\d{4}:input/)
Note:
You will need to verify that this regex will not end up also matching other elements on the page. If it does, you will need to make your search more specific by using other information about the element (perhaps the class) or information around the element (perhaps the field's label).
Depending on the other elements on the page, this regex might be more specific than you need. For example, perhaps just the first part is unique. In that case you could just do /form:wrap:j_idt/.

Resources