Rendering a portion of a Play framework 2.0 template - java

I'm trying to call render from a controller for a tag (function) inside a template instead of the template. This way I could use it for partial renderings of a page from ajax calls. Of course I could separate the components of the form in several templates an call render on those but I think it would be cleaner the other way.
What I was trying to do is like the following:
formpage.scala.htm
#()
<html>
...
#content
...
</html>
#**********************************
* Helper generating form *
***********************************#
#content() = {
<h3 class="form-heading">#Messages("employees")</h3>
#form(routes.AppController.save()) {
#inputText...
...
}
And using ajax render the content function, without having to separate it to a
separate file. This way I could render portions of the template without fragmenting it
in multiple files.

De facto the tag is just smaller template, so you can use tags for both - using in templates and controllers, the simplest sample:
/app/views/tags/mytag.scala.html
This is my tag...
In controller can be rendered as:
public static Result createFromTag(){
return ok(views.html.tags.mytag.render());
}
In other template you just to insert:
....
And there is my tag rendered
<b>#tags.mytag()</b>
More flexibility
Of course as it's template ergo Scala function as well you can just pass some params to it or even Html body:
/app/views/tags/othertag.scala.html
#(headline: String)(body: Html)
<h3>#headline</h3>
<div class="tagsBody">
#body
</div>
In controller can be rendered as:
public static Result createFromTag(){
return ok(
views.html.tags.othertag.render(
"Head from controller",
new play.api.templates.Html("This code becomes from <i>controller</b>")
)
);
}
(of course you can import these two for shorter code in action import play.api.templates.Html; and import views.html.tags.othertag)
Finally in your template you can use the tag as:
And there is my tag rendered <br/>
#tags.othertag("Head from template"){
some content for the tag's body from <b>The Template!</b>
}
final.
You'll find tags description in documentation.

Related

Pass html data to Quarkus Template

I am using Quarkus Mailer and Quarkus Template to create an endpoint that will be responsible just for sending emails. For now it just receives the subject, body and the emails that the email should be sent to. I am using Quarkus Template so that I have a base html template for all emails. However I want to be able to pass html through the endpoint so that I am able to render different styles in the content of the template.
This is the part of the template where the body is rendered:
<tr style='mso-yfti-irow:5;height:343.95pt'>
<td width=621 valign=top style='width:466.05pt;border-top:none;border-left: solid #0E133C 2.25pt;border-bottom:none;border-right:solid #0E133C 2.25pt; padding:2.0cm 1.0cm 1.0cm 1.0cm;height:343.95pt'>
<p class=MsoNormal><span lang=PT style='mso-ansi-language:PT'>{sendEmailRequest.getBody()}<o:p></o:p></span></p>
</td>
</tr>
Basically the "sendEmailRequest.getBody()" has the html content and it is currently being rendered like this:
This is the code used to send the email:
public void sendEmail(final SendEmailRequest sendEmailRequest) {
final String html = template.data("sendEmailRequest", sendEmailRequest).render();
mailer.send((new Mail()).setSubject(sendEmailRequest.getSubject())
.setHtml(html)
.setTo(sendEmailRequest.getTos()));
}
Keep in mind that I want to keep using a base template for the email and not directly use the body received from the DTO as the whole email body. I already managed to use html from the endpoint, but that was wihtout using the template.
I posted the same question as an issue in the Quarkus repository and the solution was provided.
You can check it ou here: https://github.com/quarkusio/quarkus/issues/23893
The solution:
You need to output the unescaped value: (1) either use the raw or safe computed properties in the template ({content.raw} or {content.safe}) or (2) wrap the String value in a io.quarkus.qute.RawString (template.data("content", new RawString(content)).render()).
You can use #eval in your template to display raw html
{#eval htmlContent /}

Java Play Framework creating logged in navigation bar - inserting dynamic html in scala template

I am working with Play Framework in Java, creating simple website with OAuth and Bootstrap. My goal is to have navigation bar showing logged in user after authentication - So I need dynamic creation of html code for navigation bar. Many people would instantly suggest using scala template parameters to create that dynamic content:
navigation.scala.html
#(loggedInUser: String)
<div class="navbar">
<div class="containter">
<ul class="nav navbar-nav navbar-left">
<li>Logged in as: #loggedInUser</li>
</ul>
</div>
</div>
main.scala.html
#(loggedInUser: String)(content: Html)
<!DOCTYPE html>
<html lang="en">
<body>
#navigation(loggedInUser)
#content
</body>
</html>
This seems fine but as application grows there is going to be much more templates which have to call main template, and in every single one I will be passing parameter loggedInUser just so it would reach navigation. It's just becoming big stack of parameters on each template. So is there any way to get this loggedInUser string directly, not by passing it through called templates? I tried to solve it with having static Controller as Utility which would fetch me username which I would do by putting username in session attribute in moment of authorization and then pulling it with "Utility Controller":
public class UsernameController extends Controller {
public static String getLoggedInUsername() {
return ctx().session().get("username");
}
}
and then changing navigation.scala.html to:
#()
<div class="navbar">
<div class="containter">
<ul class="nav navbar-nav navbar-left">
<li>Logged in as: "#routes.UsernameController.getLoggedInUsername()"</li>
</ul>
</div>
</div>
But this also doesn't work good because Controller is static, and for e.g. when it comes to Dependency Injection (in my case using pac4j for OAuth) of factory classes, you cannot use static methods (I know there is static injection solutions but it is not recommended for use). I hope there is some way of using methods in scala templates which generate html so I can use it to inject it into navigation.scala.html (method would have access to Session and all attributes so I could get info about the current user)
You can use Deadbolt to take care of this, using the #subjectPresent and/or #subjectPresentOr template constraints. The former only allows rendering to occur if a user is logged in, and the latter renders alternative content if no user is logged in, e.g.
#import be.objectify.deadbolt.java.views.html.{subjectPresent, subjectPresentOr}
#subjectPresent() {
This content will be present if handler#getSubject results in a Some
}
#subjectPresentOr() {
This content will be present if handler#getSubject results in a Some
} {
fallback content
}
Take a look at the Deadbolt Java documentation for more details.
However, if you need user details to be displayed in the template then you really should be passing that information into the template.
Using <li>Logged in as: "#routes.UsernameController.getLoggedInUsername()"</li> is an approach that is not clean and very possibly not thread-safe. Twirl templates are type-safe and parameterized for a reason!

Play framework 'set' template tag not working between files

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

Using HTML builders in grails instead of GSP

is there a way to use groovy builders to build JSP files in a Grails application keeping things enough integrated?
To explain better: by default Grails uses gsp files that are nice but quite verbose..
<div class="clear">
<ul id="nav">
<li><g:link controller="snippets" action="list">Snippets</g:link></li>
<li><g:link controller="users" action="list">Users</g:link></li>
<li><g:link controller="problems" action="list">Problems</g:link></li>
<li><g:link controller="messages" action="list">Messages</g:link></li>
</div>
<div id="content">
is there a way to use groovy.xml.MarkupBuilder tha would turn the previous piece into
div(class:'clear') {
ul(id:'nav') {
li { g_link(controller:'snippets', action:'list', 'Snippets') }
// and so on
Of course g_link is invented just to give the idea..
Do a search for builder under the web layer section of the grails user guide. There is an example in there that shows you exactly how to do this using the xml builder.
I don't have a complete answer for you, but I suspect the key will be gaining access to the "view resolvers". In a normal SpringMVC app, these are configured in views.properties (or views.xml) as follows:
csv=com.example.MyCSVResolver
xml=com.example.MyXMLResolver
audio=com.example.MySpeechResolver
In a regular SpringMVC app, you return something like new ModelAndView(myModel, 'csv') from a controller action.
This would cause the CSVResolver class to be invoked passing it the data in myModel. In addition to containing the data to be rendered, myModel would likely also contain some formatting options (e.g. column widths).
Spring searches the views file for a key matching the view name. If it doesn't find a match, by default it just renders a JSP with the view name and passes it the model data.
Now back to Grails....remember that Grails is really just a Groovy API over SpringMVC and most of the features of SpringMVC can be accessed from Grails. So if you can figure out how to modify the views file, just change your controller actions to return an appropriate ModelAndView instance, and it should work as described above.
GSP allows you to run arbitrary Groovy code inside <% %> brackets. So you can have something like this (borrowing example from page linked to by BlackTiger):
<% StringWriter w = new StringWriter()
def builder = new groovy.xml.MarkupBuilder(w)
builder.html{
head{
title 'Log in'
}
body{
h1 'Hello'
builder.form{ }
}
}
out << w.toString()
%>
Note that the above calls g:form tag, and you can pass additional stuff to it.
So what you are asking for is certainly possible, though I am not sure if it will end up being a win. I'd suggest you perhaps look more at TagLibs in combination with Templates and SiteMesh Layouts - can definitely simplify things tremendously.

Velocity #parse but assign it to a variable

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")

Categories