I've just installed grails rendering plugin and would like to use it for generating PDF files. I've created simple template, but it is exported without any css styles. If I simply render template from grails, then page appears with all styles in my web browser.
So, my question is - how to correctly include CSS file during PDF generation process?
My template:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<link rel="stylesheet" href="${resource(dir:'css',file:'main.css')}" />
<link rel="stylesheet" href="${resource(dir:'css',file:'webui.css')}" />
<r:layoutResources/>
<title>Report</title>
</head>
<body>
<div id="content">
<div id="center-container">
<h1><g:message code="default.list.label" args="[entityName]" /></h1>
<table>
<thead>
<tr>
<th class="trip">trip</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>
${tip}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
And I have style .odd in my webui.css, but it is not applied on the row.
Any help would be appreciated.
Edit1: I found out that styles are fetched, if I do it in the following way:
<link rel="stylesheet" href="my_appname${resource(dir:'css',file:'main.css')}" />
But I don't want to hardcode application name (this is also a base context path). Is there a better way to generate proper link to a css file?
It may be late with my answer but I wanted to share my experience here with rendering pdf in grails. I followed the below steps and failed over to the next until I get a pdf:
Used the resource plugin in the template gsp to grab a module where css was bundled.
For example:
Test.gsp
<html>
<head>
<r:require modules="bootstapApp"/>
<r:layoutResources/>
</head>
<body>
....
<r:layoutResources/>
</body>
</html>
The above worked fine but the styles were not used in the pdf after rendering. I had to fall over to step 2.
2.Started using tag as mentioned above in the problem statement.
Result: No change. I wasn't able to get the styles in the pdf.
Failed over to step 3
3.Added the styles inline in the template gsp. And then I was able to apply them to the pdf. Point to note here is that if you follow step 3 and you have css like bootstrap.css then inlining them in the template will be cumbersome. Even if we add them, do not forget to put them inside the media tag. For me the below worked perfectly fine:
<style type="text/css">
#media all {
//CSS styles goes here
}
</style>
Try setting grails.serverURL in Config.groovy to the app url (ex. grails.serverURL=http://localhost:8080/appname). The plugin resolves all relative links via this setting
I shared my answer elsewhere, but I ended up just embedding the external file contents into the gsp for pdf rendering:
https://stackoverflow.com/a/32767378/1599616
Related
I'm trying to convert simple html to pdf but the styling in my browser is different than the one in pdf. I'm using flying-saucer-pdf v9.1.18. Do you have any idea why?
here is how it looks on web browser and how it looks in the generated pdf:
https://i.stack.imgur.com/MB7DB.jpg
Here is my simple html template:
<html>
<head>
<style>
.aligned {
vertical-align: bottom;
}
.colored {
color: red;
font-weight: bold;
}
</style>
</head>
<body>
<table border="1" width="300px" height="300px">
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td class="colored">4</td>
</tr>
<tr>
<td>5</td>
<td class="aligned">6</td>
</tr>
</table>
</body>
</html>
From docs:
No support for legacy or "street" HTML, although there are several
open source Java HTML cleaners of varying quality available. We render
well-formed XML; XHTML is a well-formed XML document which uses a
special set of tags. We can't render most HTML "in the wild". At best,
you can "clean up" old HTML with TagSoup or JTidy or similar library
and hope for the best. But without a bunch of work, you won't be able
to use Flying Saucer for a real web browser component. However, note
that's not a technical limitation, just a lack of time and resources.
The "height" attribute of TABLE tag is standard at all, I guess flying-saucer is ignoring it.
See e.g. Setting the height of a table in HTML has no effect
I have two tables that are supposed to be side by side on the same line.
One table ("stableTable") is always on the right side of the viewable area, and the other table ("movingTable") can be modified to have its align be left, center or right.
Here's the HTML Code
<html>
<head>
<!--Test Header-->
<style>
body {display: inline; width: auto;}
table {width: auto;}
table, th, tr, td {border: 1px solid;}
</style>
</head>
<body>
<table class="stableTable" align="right">
<tr>
<td>
WORLD
</td>
</tr>
</table>
<table class="movingTable" align="right">
<tr>
<td>
HELLO
</td>
</tr>
</table>
</body>
</html>
When I put this in an HTML file and open the browser it shows up correctly as seen below (both side by side):
But here's the output when I put this same HTML code in a JEditorPane (one is on top of the other):
I'm stumped on this one as I have tried different things in an HTML file that appears correct when I open it up on a browser, but it doesn't in the Java JEditorPane.
Any thoughts?
EDIT:
After looking online a little, it appears that Java has a poor track record for rendering HTML and CSS correctly. I found an article that mentioned downloading flyingsaucer jar file (I ended up downloading the flying-saucer-core-9.0.4.jar version) and it appears to render the HTML side by side as I wanted.
Now my only task is to get it to work within the existing maven project I'm working in with the actual tables.
I believe the issue here is with the JEditorPane itself and that it (and Java itself) has a poor track record of rendering HTML/CSS.
I have found that using flying saucer 3rd party app is the way to go. I have tested with that and it does render the HTML as I want.
Here's the link to the specific flying saucer version that I used https://mvnrepository.com/artifact/org.xhtmlrenderer/flying-saucer-core/9.0.4
I am about to re-write a web-platform, and I am using Spring Boot/Spring MVC. A major part of the platform is the website. I am struggling deciding which template-engine to use. Thymeleaf seems to be recommended, while JSP discouraged. I am not sure if my requirements are unusual, at least they do not sound like that to me:
I do not want to repeat myself in the different templates, they should all be displayed inside a "master template/layout"
The master template/layout will have navigation and footer, which have dynamic content (eg. it is not only the main content that is dynamic)
1) With Thymeleaf, from what I have been able to understand, using Layouts would be the recommended (only?) approach. However, it looks to me like all dynamic content much still be generated in each template (where it flows into the layout using the layout:fragment attribute). This sounds less than ideal, as it would mean I would still have to generate the dynamic part of the layout in each template. Is there no way to include dynamic content in Thymeleaf layouts, where the content (menu, footer, twitter-feed etc) is generated separately from the actual content-template?
2) JSP seems to be able to solve this rather easily, using a custom tag for the layout, that has <jsp:include> -tags for the dynamic content and a <jsp:doBody> -tag for the actual content-template. However, from reading the Spring Boot documentation, I somehow got the impression that it is encouraged to use a different template-engine that JSP. The approach described above would however let me define a header.jsp, navigation.jsp, footer.jsp and twitterFeed.jsp that generates the content dynamically (based on database content, logged in user etc), while the actual content-template purely focuses on the content to display. Is there something I am missing in my comparison between Thymeleaf and JSP here, why would I not chose JSP as my project's template engine?
3) With the approach meantioned in 2), would I be limited to putting all my Java logic in the JSPs for the templates included in the main layout (header, navigation, footer, twitter-feed), or is there a better way to back these stubs up with a controller-like class?
4) Are there any other template engines that integrate well with Spring MVC / Spring Boot, that would be a better choice that any of the above mentioned ones?
Use can use Thymeleaf Ultraq Layout to create a base template which will act as a decorator for your other templates as shown below:
base-template.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<title layout:title-pattern="$CONTENT_TITLE - $LAYOUT_TITLE">Sample</title>
<meta name="description" content=""/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<!-- all CSS links here -->
</head>
<body>
<div class="container">
<div class="content">
<div layout:fragment="page_content">
<!-- Content from other pages which decorate using this template -->
</div>
</div>
</div>
<!-- /.container -->
<!-- All script tags here -->
<th:block layout:fragment="scripts">
<!-- If you have any page specific scripts -->
</th:block>
</body>
</html>
Then the other pages will use the above template as a decorator as shown below:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{base-template}">
<head>
<title>This page title</title>
</head>
<div layout:fragment="page_content">
<!-- content for this page -->
</div>
<th:block layout:fragment="scripts">
<!-- add any scripts related to this page -->
</th:block>
</html>
The syntax ~{base-template} is used with Thymeleaf 3 onward.
You can proceed with the above approach and not repeat the navigations, headers and footers on your other pages.
I have been using Sitemesh 3 for my project and so far it's been working great. Recently I came across a situation where I am stuck.
My final view has to be composed of 2 html files, both have their own and tags.
File1:
<html>
<head>Head1</head>
<body>body1</body>
</html>
File2:
<html>
<head>Head2</head>
<body>body2</body>
</html>
I am composing a view using freemarker include tag. So, the composed HTML looks like:
<html>
<head>Head1</head>
<body>body1</body>
</html>
<html>
<head>Head2</head>
<body>body2</body>
</html>
Following is my decorator:
<html>
<head>
<sitemesh:write property='head'/>
</head>
<body>
<div class="container">
<sitemesh:write property='body'/>
</div>
</body>
</html>
But once decorated, the final output I am getting is:
<html>
<head>
<head>Head1</head>
</head>
<body>
<div class="container">
<body>body1</body>
</div>
</body>
</html>
But the expected output is
<html>
<head>
<head>
Head1
Head2
</head>
</head>
<body>
<div class="container">
body1
body2
</div>
</body>
</html>
I came across a similar question, but that solution won't work for me because I don't want to create multiple decorators.
I just want to know if it's possible in Sitemesh 3. If yes, then how.
Thanks.
If you don't mind extending Sitemesh 3 then this is fairly easy to do by adding support for server side includes in your decorator template. I do exactly this in another library (UtterlyIdle).
I'm using StringTemplate as my decorator language but this should work in Freemarker or any other templating tool. I add in a PageMap and then in my decorator template call
$include("someUrl").body$
This does a include and then parses the output with the Sitemesh 3 engine. This allows you to have as many includes as you like.
Hope that makes sense
Something very weird is happening when I try to edit my index.html file .
I'm working with jsp-s and servlets , in Java.
When I try to update one of the fields , for instance :
<!DOCTYPE html>
<html>
<head><title>Bank application</title>
<link rel="stylesheet"
href="./css/styles.css"
type="text/css"/>
</head>
<body>
<table class="title">
<tr><th>Bank application</th></tr>
</table>
<br/>
<fieldset>
<legend>Bank Account Balance</legend>
<form action="show-balance">
Customer ID (id001, idffffffffffffffffdsafds002, id003):
<input type="text" name="cusdddddddddddddddddddddddddddtomerId"/><br/>
<input type="submit" value="Sddddddddddddddddddddddddddddddddddddddhow Balance"/>
</form>
</fieldset>
<br/>
// from here, the rest is the same as the above
I get this (same as before) :
Why when changing the index.html file , no change takes place ?
I'm using :
Apache 7
Xampp
Thanks
Browsers will cache HTML files unless you explicitly tell the browser to refresh (ctrl + F5). I'm guessing you're just loading the cached version of the HTML.