Say you have a standard template with included (parsed) header, body, footer templates.
In the body template a variable like $subject is defined and you want that also displayed in the header template.
In some other template languages like HTML::Mason(perl based) you would evaluate the body template first to pick up the $subject variable but store it's output temporarily in a variable so your final output could end up in the correct order (header, body, footer)
In velocity it would look something like
set ($body=#parse("body.vm"))
parse("header.vm")
${body}
parse("footer.vm")
This however doesn't seem to work, any thoughts on how to do this?
Either of the two solutions above would work. The VelocityLayoutServlet solution requires an extra package (also from Velocity) called Velocity Tools. I'm partial to this approach (and variants) myself.
A third method is simply to put the #parse within quotes:
set ($body="#parse('body.vm')")
Within a #set, anything in double quotes is evaluated. Strings within single quotes are passed in literally.
You can do this using VelocityLayoutServlet which is part of VelocityTools.
This allows you to define a layout for your application -- let's call it application.vm -- in which you can parse in headers, footers etc and declare where the main body content is placed using the screen_content declaration, e.g:
<html>
<head>
<title>$subject</title>
</head>
<body>
#parse("header.vm")
$screen_content
#parse("footer.vm")
</body>
</html>
VelocityLayoutServlet will evalulate the templates (and, hence, variables) before rendering which allows you to set a $subject variable in your body template, e.g:
#set($subject = "My Subject")
<div id="content">
</div>
More detailed information can be found in the Velocity documentation.
If I understand you correctly, you want to have a Velocity variable named $subject interpolated into the header.vm and the body.vm templates. Right now, the variable is defined in the body.vm template, so you cannot refer to it in the earlier template header.vm.
Why don't you abstract out the definition of $subject into its own template snippet, called globals.vm say, then include that in the top-level template. So you'd have:
#parse("globals.vm")
#parse("header.vm")
#parse("body.vm")
#parse("footer.vm")
Related
I use Thymeleaf as a templating engine and I usually output variable value like this:
in Java I set:
ctx.setVariable("tester", "hello");
and in html template I output:
<span th:text="${tester}"></span>
This works great, but I would like to output a variable without the need of a tag. Something following would be great:
${tester}
Unfortunately it does not work. My goal is to avoid unnecessary tag to output the variable value. Is this possible to do with Thymeleaf?
My goal is to avoid unnecessary tag to output the variable value. Is this possible to do with Thymeleaf?
Yes this is possible. You can use the Thymeleaf synthetic th:block tag (see here).
Example template excerpt:
<body>
<th:block th:text="${tester}"></th:block>
</body>
This renders the following HTML:
<body>
hello
</body>
Only the variable is displayed.
Use Thymeleaf expression inlining (docs) using either [[...]] or [(...)]. With expression inlining, you do not need to use synthetic tags.
Example:
<body>
The value of tester is [[${tester}]].
</body>
Thymeleaf triggers on the "th:" tag and as far as I know thats the only way.
The behaviour you describe works with JSF.
Best regards
Ben
I also managed to figure out some workaround:
<span th:text="${tester}" th:remove="tag"></span>
th:remove removes span tag, but preserves content.
I'm working on a componentization system based on JSPs. This means that parts of the JSP can be moved from one JSP to an other one via drag and drop and leads to a need for a local page scope as variable of a component defined in one JSP my collide in an other JSP.
I can use Servlet 3.0 / JSP 2.2 / JSTL 1.2.
++ Tag File ++
The straight way of doing that would be to create a tag file for a component or something similar as they have this local page scope. But for every change in the tag file it would need to get redeployed and needing to create a tag file needs some time by itself. But if there is no other solution this direction (custom tags, tag files, JSP includes,...) is probably the way to go.
++ Namespace prefixing/suffixing ++
In Portlets one is supposed to concatenate each variable with a namespace provided from the portlet response object. I could do something similar but this can lead to side effects and unexpected behavior. If someone forgets to prefix/suffix the namespace it might work for some time but stops working at an other time without changing the code when the component moved to an other JSP with a conflicting variable name.
++ Custom Tag wrapping ++
I was hoping that I as a component framework developer can wrap the component code of a component developer with a tag file for a component tag like this
<a:component>
<div data-component-id="9">
<c:set var="componentId" value="9"/>
<c:set var="path" value='${abc:getCurrentPath()}_${componentId}'/>
<c:set var="resource" value='${abc:getResourceFromPath(path)}'/>
<c:set var="val" value="${resource.getValue('paragraphValue')"/>
<p><c:out value="${value}"/></p>
</div>
</a:component>
to have the variable in the local page context of the tag file. But instead they are in the context of the surrounding page. I'm looking for something like this
<% { %>
<div data-component-id="9">
<%
String componentId = 9;
String path = obj.getCurrentPath()+componentId;
Resource resource = otherObj.getResourceFromPath(path);
String value = resource.getValue("paragraphValue");
%>
<p><c:out value="<%=value%>"/></p>
</div>
<% } %>
which would create a code block in which variables have their own namespace. But of course for JSTL and JSTL-EL instead of scriptlet code.
I had a look at the JSTL specification but did not find out if there is a way to create such a local page scope. But I didn't check everything as it's huge and I'm not sure if it's possible with custom tags.
It is clear to me that bigger code blocks should not be in the JSP but with the framework I would like to provide simple solutions for smaller components.
++ Changing the JSP code ++
When components are initially placed on a JSP or moved around via drag 'n drop I actually move the JSP code of a component from one JSP to an other or within a JSP. This means I can also programmatically manipulate the JSP code of a component if it doesn't get too complex and it helps solving the problem.
As I thought that custom tag wrapping could be the ideal solution I created an other more specific question and I've got an answer here that solves the problem.
It's simply to remove all pageContext attributes before the evaluation of the body and adding them again at doEndTag().
I get html code from server to build freemarker.ftl.
Example:
Server return:
String htmlCode="<h1>Hello</h1>";
freemarker.ftl
${htmlCode}
except:Hello
actually: <h1>Hello</h1>
what can i do?
By default FreeMarker has no auto-escaping on, so it should print that value as HTML. But as it doesn't as you say, I can imagine two possibilities:
You are inside <#escape x as x?html>...</#escape>, or that was added to the template by a custom TemplateLoader. In that case, in 2.3.x you have to write <#noescape>${htmlCode}</#noescape>. (In 2.4 it will be much less verbose if everything goes as planned.)
That value was escaped before it reaches FreeMarker. So the template already gets <h1>Hello</h1> as the string.
I'm working on a project using play framework 1.2.5
I have two custom tags files, one that does 'set' a value
#{set foo:'bar' /}
and another file that 'get' this value to make a decision to show some markup or not.
%{ if(foo) { %}
#{doBody /}
%{ } }%
This used to work in a previous play version (don't recall which) and now is not working, I'm not sure if it was the upgrade itself or something else got broken.
As per play documentations for template engine tags, set should work between different files:
Define a value which can be retrieved in the same template or any layout with the get tag.
http://www.playframework.com/documentation/1.2.3/tags#set
Any clue on what might be wrong?
thanks in advance
set only works with child template passing data to extended template, e.g
parent template:
<html>
<title>${get 'title'}</titl>
...
</html>
child template:
$extends('parent.html')
${set title: 'My Title'/}
To pass data from one template to another template, you have to define the callee template as a tag. See play's document on more detail. Note I am not sure if tag could extend another tag, most probably it is not possible
If you are using PlayRythm plugin, then it is much easier. E.g. calling from template foo to bar could be as easy as
bar template:
Hello #who
foo template:
#bar("World")
#// or
#bar(who: "world")
#// or
#bar({who: "world"})
Note Rythm doesnot have a separate tag concept, literally every template is tag and you can call any template from another one or even do recursive call. You can try rythm's live interactive demo on http://fiddle.rythmengine.org/.
Disclaim: I am the creator and maintainer of Rythm template engine and Play-Rythm module
I'm trying to do a macro on freemarker, but I'm having problems to implement css class as parameter.
My object have some default css classes and I would like to add optional classes.
<#macro Button href extra...>
<a href="${href}" class="ui-button"
<#list extra?keys as attr>
${attr}="${extra[attr]?html}"
</#list>
>Anchor Button</a>
</#macro>
1) <#Button href="link.html"></#Button>
2) <#Button href="link.html" id="button1" class="marginrightnone"></#Button>
The line 2) only is rendering the "id" parameter. If I delete class="ui-button" of the macro, then it renders correctly.
What I could to do to render two or more class parameters???
You need to construct a string containing all the class parameters and use that as the value of a single HTML class attribute in the template.
You can't have an arbitrary number of class attribute/value pairs and still be legal HTML.
The simplest that would be basically what you have now would be to create a local with the "ui-button" value in it. As you iterate over extra?keys check for a "class" key and if found, append it to the local class (along with a leading space). The template would use that constructed value:
<a href="${href}" classes="${local_classes}"