I'm using Spring Boot with some templates to help generate some dynamic emails. Unfortunately, the templating engine isn't rendering my variables.
Backend Call
public String generateProblemOfTheDay(Model model) throws IOException {
Context ctx = new Context();
ctx.setVariable("potd", "Test Value");
//Process the template with the proper context variables
String html = templateEngine.process("index", ctx);
PrintWriter pWriter = new PrintWriter(Paths.PROBLEM_OF_THE_DAY_OUTPUT, "UTF-8");
pWriter.println(html);
pWriter.close();
log.info("done!");
log.info(html);
return html;
}
Segment of my template
.
.
<tr>
<td style="font-family:'Open Sans', Arial, sans-serif; font-size:15px; line-height:18px; color:#30373b;">
<br />
<div class="question-description">
[[${potd}]]
</div>
</td>
</tr>
.
.
I'm not sure why the template engine isn't processing the variables correctly. Is this the best way to add variables?
What I found does work
<label style="font-size: 12px;padding-bottom: 1em;" th:text="${potd}">Test</label>
Adding something like the following does indeed work.. I've seen many people use t he standard curly bracket notation without issues and wondering what is appropriate where.
Inlined expressions were changed from thymeleaf 2 to 3. I'm guessing you're using thymeleaf 2, which means you need the attribute th:inline="text" in order to get your expression to work.
<div class="question-description" th:inline="text">
[[${potd}]]
</div>
If you upgrade to thymeleaf 3, those expressions will work out of the box (and it even recommends you remove th:inline="text"). As for which way you should write expressions... it is pretty much opinion based. For the most part, I like using th:text directly in a tag. If you are appending a lot of strings together, you might use the other way. For example:
<span>Your answer was: [[${answer}]]</span>
is easier to read than
<span th:text="${'Your answer was:' + answer}"/>
Related
I'm building an app with Java and Thymeleaf and I need to pass a HashMap to a partial. I don't want to pass it from a controller.
This is what I tried so far:
user.html
<div th:replace="partials/icons.html :: icons(icons=${ {name='user', title='User'}, {name='blog', title='Blog'} })"></div>
/partials/icons.html
<div th:fragment="icons">
<th:block th:each="icon : ${icons}">
<button th:class="'icon-' + ${icon.name}" th:text="${icon.title}"></button>
</th:block>
</div>
It gives me an error that = is unexpected. What would be the correct syntax?
EDIT: I should have clarified up-front: there is no way to do what you are trying to do with the syntax of fragment parameters. My approach below is a work-around.
Assuming you have the following object as a starting point:
public class Icon {
private String name;
private String title;
// getters and setters...
}
Assuming you then have a List of such objects, called icons...
This list is passed to your Thymeleaf renderer in the usual way. I don't use Spring, so how you do that is (I assume) through an annotation. I may be wrong - it shouldn't affect the approach below, however. In my no-Spring approach the list is added to the Thymeleaf model as map.put("icons", icons);
I have the following in my parent Thymeleaf template:
<div th:replace = "/iconsfragment.html :: icons(iconlist='icons')">
</div>
I have the following in iconsfragment.html:
<div th:fragment="icons(iconlist)">
<th:block th:each="icon : ${__${iconlist}__}">
<div th:class="'icon-' + ${icon.name}" th:text="${icon.title}"></div>
</th:block>
</div>
It uses a preprocessor __${...}__ to convert the parameter (a string) back into an iterable object.
The resulting HTML that you care about is:
<div class="icon-firstName">firstTitle</div>
<div class="icon-secondName">secondTitle</div>
This only really makes sense if you want to re-use that fragment in various different ways, of course. Otherwise just pass the ${icons} object directly to the fragment.
And my <div> example would of course need to be adapted to your <button> example.
im new to thymeleaf and Spring - im doing some small project to my school class and i have a problem with html link. I had troubles with it for 2hours now and im editing my code in 10 diffrent ways so please answer how to do it properly. Below its my html template (i tried using here th:href with two diffrent ways:
<table>
<th>Name</th>
<th>Date</th>
<th>See</th>
<th>Edit</th>
<a th:each=" i : ${workouts}" varStatus="status">
<tr>
<td><a th:text="${i.getName()}"/></td>
<td><a th:text="${i.getDate()}"/></td>
<td>See</td>
<td>See</td> </tr>
</a>
</table>
And here its my Controller:
#Controller
public class SeeWorkoutController {
#RequestMapping(value = "/seeWorkoutPage/{id}", method=RequestMethod.GET, params="id")
public String test2(#PathVariable("id")Long id, Model model) {
System.out.println(id);
return "workoutsPage";
}
but it's now working properly. Please help.
Check the documentation for Thymeleaf Link URLs. In particular this example:
<!-- Will produce '/gtvg/order/3/details' (plus rewriting) -->
view
I think you're almost there with your second example, but it should read
th:href="#{/seeWorkoutPage/{workoutId}(workoutId=${i.getId()})}"
Note how you specify the {workoutId} parameter, then give it's value between the brackets afterwards.
Try:
<span th:each="workout: ${workouts}">
<td><a th:text="${workout.name}"/></td>
<td><a th:text="${#dates.format(workout.date,'MMM d, yyyy')}</td>
<!-- add other stuff when you have the above working -->
</span>
You don't need the get() syntax (and it can throw an exception in some containers). Also, it looks like you're nesting anchor (<a>) tags too.
I am developing an MVC web app using spring framework.
At some point I have a jsp that is listing study case objects as sown below
<tbody>
<c:forEach items="${studycases}" var="studycase">
<tr>
<td>
<a href='<spring:url value="/studycase/${studycase.study_case_number}.html"/>'>
${studycase.study_case_number}
</a>
</td>
<td>
${studycase.dateOFHospitalAdmission}
</td>
<td>
${studycase.dateOfWardAdmission}
</td>
<td>
${studycase.dateOfWardDischarge}
</td>
</tr>
</c:forEach>
</tbody>
as you can see there is a spring:url that is directing to a jsp with details about the spesific study case, that is being handled by the below controller :
#RequestMapping("/studycase/{studyCaseNumber}")
public String detail(Model model, #PathVariable String studyCaseNumber)
{
model.addAttribute("studyCase", studyCaseService.findOne(studyCaseNumber)) ;
model.addAttribute("measurements", measurementService.findAllOfThem(studyCaseNumber)) ;
return "study-case-detail" ;
}
The problem is that as the study cases listed in the first jsp could be thousands I will need to make it possible for the user to enter the study_case_number of a study case in a input field and get the details of the study case having the study case number inputed . So what I am doing is this:
<form action="<spring:url value="/studycase/study-case-detail2"/>" method="GET">
Study Case Number : <input type="text" name="studyCaseNumber">
<br/>
<input type="submit" value="Submit" />
</form>
That is being handled by an other controller and directs to an other jsp with more or less the same structure and data :
#RequestMapping("/studycase/study-case-detail2")
public String detail2(Model model, #RequestParam("studyCaseNumber") String std)
{
model.addAttribute("measurements", measurementService.findAllOfThem(std)) ;
return "study-case-detail2" ;
}
My question is this : Is this a good way to go having different controllers and different views even if they are presenting more or less the same thing ? What are other alternatives ??
Is there any source that you can direct me to containing best practices catalogue or guide on how to handle similar situations ??
Looking at your code, your controllers are not doing exactly the same thing (e.g. different model attributes, and they return different views).
Other than that, in general, it's not the best practice to do what you're doing as it somewhat in conflict with "Do Not Repeat Yourself" principle (also known as DRY principle).
One suggestion would be to use javascript to do redirect on id from input box rather than a form.
It seems you're using Spring Data too. If that's the case then one additional (not exactly related) suggestion to DRY up your code would be to use Spring Data's domain class converters to avoid calls studyCaseService.findOne(studyCaseNumber) in your StudyCase related controllers.
With domain class converters in place, you could then write controller method like this:
public String detail(Model model, #PathVariable("studyCaseNumber") StudyCase studyCase)
and avoid call to repository's findOne method as the converters would automatically convert ID to entity.
Take a look at DomainClassConverter in "Basic Web Support" section of Spring Data manual:
http://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html
I am a beginner on developing Android's application. I have some problems about using regular expressions in Android.
In my application, I had write some code for get back the source code of a html page which I had turn it in String datatype.
And now I want to use regular expressions to retrieve some details in the html tags of this page. So, what should I do for it?
for example, in the html code,
<HTML>
.......
<TABLE class=tb_info cellSpacing=0 cellPadding=0 border=0>
<TR>
<TD class=pro_name vAlign=center colSpan=5>Abby Poon</TD>
</TR>
<TR>
<TD class=pro_name vAlign=center colSpan=5>Peter Pan</TD>
</TR>
</TABLE>
.........
</HTML>
And now I want to get back the value "Abby Poon" and "Peter Pan" which is in a table called "tb_info" and in a called "pro_name" for both two values.
Can anyone teach me how I can do it? Or you may give me some reference page for it with Android.
Thank you very much.
Do not parse HTML using regular expressions.
Instead, use an HTML Parser.
HTML is not a regular language, therefore you cannot use Regular Expressions against it 100% successfully. You need to use some sort of HTML parser instead.
You don't want to be driven insane.
Embedded custom-tag in dynamic content (nested tag) not rendering.
I have a page that pulls dynamic content from a javabean and passes the list of objects to a custom tag for processing into html. Within each object is a bunch of html to be output that contains a second custom tag that I would like to also be rendered. The problem is that the tag invocation is rendered as plaintext.
An example might serve me better.
1 Pull information from a database and return it to the page via a javabean. Send this info to a custom tag for outputting.
<jsp:useBean id="ImportantNoticeBean" scope="page" class="com.mysite.beans.ImportantNoticeProcessBean"/> <%-- Declare the bean --%>
<c:forEach var="noticeBean" items="${ImportantNoticeBean.importantNotices}"> <%-- Get the info --%>
<mysite:notice importantNotice="${noticeBean}"/> <%-- give it to the tag for processing --%>
</c:forEach>
this tag should output a box div like so
*SNIP* class for custom tag def and method setup etc
out.println("<div class=\"importantNotice\">");
out.println(" " + importantNotice.getMessage());
out.println(" <div class=\"importantnoticedates\">Posted: " + importantNotice.getDateFrom() + " End: " + importantNotice.getDateTo()</div>");
out.println(" <div class=\"noticeAuthor\">- " + importantNotice.getAuthor() + "</div>");
out.println("</div>");
*SNIP*
This renders fine and as expected
<div class="importantNotice">
<p>This is a very important message. Everyone should pay attenton to it.</p>
<div class="importantnoticedates">Posted: 2008-09-08 End: 2008-09-08</div>
<div class="noticeAuthor">- The author</div>
</div>
2 If, in the above example, for instance, I were to have a custom tag in the importantNotice.getMessage() String:
*SNIP* "This is a very important message. Everyone should pay attenton to it. <mysite:quote author="Some Guy">Quote this</mysite:quote>" *SNIP*
The important notice renders fine but the quote tag will not be processed and simply inserted into the string and put as plain text/html tag.
<div class="importantNotice">
<p>This is a very important message. Everyone should pay attenton to it. <mysite:quote author="Some Guy">Quote this</mysite:quote></p>
<div class="importantnoticedates">Posted: 2008-09-08 End: 2008-09-08</div>
<div class="noticeAuthor">- The author</div>
</div>
Rather than
<div class="importantNotice">
<p>This is a very important message. Everyone should pay attenton to it. <div class="quote">Quote this <span class="authorofquote">Some Guy</span></div></p> // or wahtever I choose as the output
<div class="importantnoticedates">Posted: 2008-09-08 End: 2008-09-08</div>
<div class="noticeAuthor">- The author</div>
</div>
I know this has to do with processors and pre-processors but I am not to sure about how to make this work.
Just using
<bodycontent>JSP</bodycontent>
is not enough. You should do soimething like
JspFragment body = getJspBody();
StringWriter stringWriter = new StringWriter();
StringBuffer buff = stringWriter.getBuffer();
buff.append("<h1>");
body.invoke(stringWriter);
buff.append("</h1>");
out.println(stringWriter);
to get inner tags rendered (example is for SimpleTag doTag method).
However, in the question's code I see that inner tag is comming from a string which is not rendered as a part of JSP, but just some random string. I do not think you can force JSP translator to parse it.
You can use regexp in your case or try to redesign your code in a way to have a jsp like this:
<jsp:useBean id="ImportantNoticeBean" scope="page class="com.mysite.beans.ImportantNoticeProcessBean"/>
<c:forEach var="noticeBean" items="${ImportantNoticeBean.importantNotices}">
<mysite:notice importantNotice="${noticeBean}">
<mysite:quote author="Some Guy">Quote this</mysite:quote>
<mysite:messagebody author="Some Guy" />
</mysite:notice>
</c:forEach>
I whould go with regexp.
I would be inclined to change the "architecture of your tagging" in that the data you wish to achieve should not be by tag on the inside of the class as it is "markup" designed for a page(though in obscurity it is possible to get the evaluating program thread of the JSP Servlet engine).
What you would probably find better and more within standard procedure would be using "cooperating tags" with BodyTagSupport class extension and return EVAL_BODY_BUFFERED in doStartTag() method to repeat process the body and/or object sharing such as storing retrived data in the application hierarchy of the session or on the session for the user.
See oracle j2ee custom tags tutorial for more information.