I am converting an existing Tiles 1 webapp to Tiles 2 architecture. I am having trouble passing values from JSP page to tiles attributes.
Here is my tiles definition file (tiles-definition.xml)
<tiles-definitions>
<definition name="cda.layout" template="/jsp/layouts/layout.jsp">
<put-attribute name="pageTitle" value="StoryTitle" type="string"/>
<put-attribute name="pageHeader" value="StoryHeader" type="string"/>
<put-attribute name="resources" value="" type="string"/>
</definition>
</tiles-definitions>
The layout.jsp looks like:
<html>
<head>
<title><tiles:insertAttribute name="pageTitle" flush="true"/></title>
</head>
<body>
...
...
<div class="content">
<h1><tiles:insertAttribute name="pageHeader" flush="true"/></h1>
</div>
...
...
</body>
</html>
I have a story page which uses the layout and need to pass values to template attributes.
<%
// create a business object and populate
String mytitle= story.getTitle();
String myheader = story.getHeader();
%>
<tiles:insertTemplate template="../layouts/layout.jsp" flush="false" >
<tiles:putAttribute name="pageTitle" value="${mytitle}"/>
<tiles:putAttribute name="pageHeader"value="${myheader}"/>
</tiles:insertTemplate>
In the story.jsp, I can System.out.print() the values for mytitle, myheader and they are showing correct. But, these values are NOT passed on to the tile attributes.
Any idea how to fix this?
${mytitle} is a JSP EL expression which means: find an attribute in page scope, or request scope, or session scope, or application scope, named "mytitle".
By defining a scriptlet variable, you haven't defined an attribute in any of these scopes. It would work if you had
pageContext.setAttribute("mytitle", mytitle);
But using scriptlets in JSPs is bad practice. I don't know where your story bean comes from, but it's probably a request attribute. If so, you can define a new page-scope attribute this way, using the JSTL:
<c:set var="mytitle" value="${story.title}"/>
This is unnecessary though, since you could use this expression directly in the tiles tag:
<tiles:putAttribute name="pageTitle" value="${story.title}"/>
Read more about the JSP EL in this tutorial.
Related
I'm using Tiles for the first time. Trying to layout my JSP pages in my Spring MVC project.
Please take a look at what I'm doing and let me know if this is the "correct" way to do it ... my specific question is at the bottom ...
I have the file structured like this ... folder /src/main/webapp/WEB-INF/layouts/ contains ...
standard.jsp
// ...
<html>
<title><tiles:insertAttribute name="title"/></title>
// ... LOTS OF HTML ...
<tiles:insertAttribute name="header"/>
<tiles:insertAttribute name="body"/>
<tiles:insertAttribute name="footer"/>
// ... LOTS OF HTML
</html>
// ...
tiles.xml
<tiles-definitions>
<definition name="standardLayout" template="/WEB-INF/layouts/standard.jsp">
<put-attribute name="title" value="My Directory" />
<put-attribute name="header" value="/WEB-INF/layouts/header.jsp" />
<put-attribute name="body" value="" />
<put-attribute name="footer" value="" />
</definition>
</tiles-definitions>
And my viewable JSPs are in folder /src/main/webapp/WEB-INF/views/ which contains ...
tiles.xml
<tiles-definitions>
<definition name="home" extends="standardLayout">
</definition>
</tiles-definitions>
home.jsp
<%# taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles"%>
<tiles:insertDefinition name="home">
<tiles:putAttribute name = "body" value="/WEB-INF/views/home-body.jsp"/>
</tiles:insertDefinition>
home-body.jsp
<div>
// LOTS OF HTML FOR THE BODY OF THE HOME PAGE
</div>
QUESTIONS: I'd like to just have one home.jsp but it looks like I have to pull the body content (and any other content) from a separate file. Is there an appropriate way to simplify home.jsp and home-body.jsp into one file, or am I actually doing this all correctly?
You need to update your tiles.xml, standard.jsp and home.jsp as below,
tiles.xml
<tiles-definitions>
<definition name="home" extends="standardLayout">
<put-attribute name="body" value="/WEB-INF/views/home.jsp"></put-attribute>
</definition>
</tiles-definitions>
standard.jsp
<html>
<title><tiles:insertAttribute name="title"/></title>
<header>
<tiles:insertAttribute name="header"/>
</header>
<body>
<tiles:insertAttribute name="body"/>
</body>
<footer>
<tiles:insertAttribute name="footer"/>
</footer>
</html>
home.jsp
<!-- Actual body content goes here.. -->
<%# taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles"%>
<p>The content of the home page.</p>
I'm using Spring MVC 3.1 and Tiles 2.
I have this Tile:
<ul class="nav">
<li class="active">Person</li>
<li>Student</li>
<li>Superadmin</li>
</ul>
And the tiles.xml:
<tiles-definitions>
<definition name="base.definition" template="/WEB-INF/pages/tiles/template.jsp">
<put-attribute name="meta" value="/WEB-INF/pages/tiles/meta.jsp" />
<put-attribute name="head" value="/WEB-INF/pages/tiles/head.jsp" />
<put-attribute name="navbar" value="/WEB-INF/pages/tiles/navbar.jsp" />
<put-attribute name="sidebar" value="/WEB-INF/pages/tiles/sidebar.jsp" />
<put-attribute name="body" value="" />
<put-attribute name="footer" value="/WEB-INF/pages/tiles/footer.jsp" />
</definition>
<definition name="user.new" extends="base.definition">
<put-attribute name="body" value="/WEB-INF/pages/user.new.jsp" />
</definition>
<definition name="user.show" extends="base.definition">
<put-attribute name="page_title" value="Tiles tutorial homepage" type="string"/>
<put-attribute name="section_title" value="User's list" type="string"/>
<put-attribute name="body" value="/WEB-INF/pages/user.show.jsp" />
</definition>
<definition name="login" template="/WEB-INF/pages/login.jsp">
<put-attribute name="meta" value="/WEB-INF/pages/tiles/meta.jsp" />
<put-attribute name="head" value="/WEB-INF/pages/tiles/head.jsp" />
<put-attribute name="body" value="/WEB-INF/pages/login.jsp" />
</definition>
</tiles-definitions>
Now, I want to set the class "active" for the selected menu.
Can I do that with Tiles? Or I have to look up with Spring?
Approach 1 - JSP/JSTL and Spring/Bean
Change your menu tile to build the menu using a list of some menu-object, which you can set on the session/model. The menu-object could have a boolean flag indicating which one to set the active class on.
Approach 2 - JavaScript/Session
If you don't want to do it this way, you could use a combination of HTML classes, JavaScript, and a session/model attributeto accomplish the task. What you would do is overload the class attribute on your LI elements, something like:
<ul class="nav">
<li class="person">Person</li>
<li class="student">Student</li>
<li class="superadmin">Superadmin</li>
</ul>
You would then have a little JS, using JSTL to get the class, to select the proper LI element and set the class. With jQuery it might look like:
$(document).ready(function() {
$('.${mySelectedClass}').addClass('active');
});
This will use jQuery to select the proper LI and add the 'active' class to it.
Approach 3 - Pure JSTL using URL
If you don't like tying your menu to the presence of an attribute, and you know your URL will, when parsed, will have some information you could use to determine which LI to set as active, you could use that. You can get the current page's URL like
<c:out value="${pageContext.request.requestURL}"/>
Parse ${pageContext.request.requestURL} in some meaningful way, and you could use it to determine which is active.
Approach 4 - Pure JavaScript using URL
Same as above, but using JavaScript to get the current URL, parse it, and manipulate the DOM as we did in approach 2.
Hopefully one of these help you.
I am using the Spring MVC framework with Apache Tiles 2. I want to be able to have multiple controllers all use the same view (different logic, some basic presentation). I can do that easily. What I want now is to have different Tiles definitions for each controller, all using the same JSP file, but each passing different template variables (page header, short description, etc). This is my Tiles template definition file:
<tiles-definitions>
<!-- Default Main Template -->
<definition name=".mainTemplate" template="/WEB-INF/templates/main.jsp">
<put-attribute name="shortTitle" value="Company ABC" type="string" />
<put-attribute name="body" value="/WEB-INF/templates/blank.jsp" />
</definition>
<!-- Overriding Templates -->
<definition name="index" extends=".mainTemplate">
<put-attribute name="title" value="Company Alpha Bravo Charlie" type="string" />
<put-attribute name="body" value="/WEB-INF/views/index.jsp" />
</definition>
<definition name="index2" extends=".mainTemplate">
<put-attribute name="title" value="Company Other Page" type="string" />
<put-attribute name="body" value="/WEB-INF/views/index.jsp" />
</definition>
</tiles-definitions>
I then try to have this /WEB-INF/views/index.jsp:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<h1>
Hello world, it's <tiles:getAsString name="title" />!
</h1>
When I load this into Tomcat and bring up the page, I get a long stack trace of exceptions. The top of the pile says org.apache.tiles.impl.CannotRenderException: ServletException including path '/WEB-INF/templates/main.jsp'.} with root cause org.apache.tiles.template.NoSuchAttributeException: Attribute 'title' not found. Anybody know what's going on?
I then try to have this /WEB-INF/views/index.jsp:
How do you try this? In your controller you would specify the name of the Tiles view, not one of the multiple JSP Tiles will use in order to render the page:
#RequestMapping("index2")
public String index2() {
// ...
return "index2";
}
I have a Tiles template where each page provides a title, some stuff to add in the <head>, stuff to put in some concrete <div>, and stuff to append to <body> after everything else.
Most of those things are very small since the page is rendered with JS.
How can I get rid of tiles.xml or make it more manageable?
I don't want each of the pages to require 3 files:
<definition name="my_page" template="/template.jsp">
<put-attribute name="title" value="My Title" />
<put-attribute name="head" value="/tiles/my-head.jsp" />
<put-attribute name="body" value="/tiles/my-page.jsp" />
<put-attribute name="body-append" value="/tiles/my-append.jsp" />
</definition>
And I don't want to put content of all pages in tiles.xml.
Ideally, it would simply redirect my_page to /my_page.jsp which would import and fill the template by itself.
I'm talking about a Spring app with TilesView.
You can use the tiles JSP tags directly in your JSP. You don't have to use definitions if you don't want to.
In your my_page.jsp:
<tiles:insertTemplate template="/template.jsp" flush="true">
<tiles:putAttribute name="title" value="My Title" />
<tiles:putAttribute name="head" value="/tiles/my-head.jsp" />
... etc
</tiles:insertTemplate>
See http://tiles.apache.org/framework/tiles-jsp/tlddoc/index.html
I have a usability problem in my Spring webapp which uses Tiles as the view technology.
At the moment all of the pages display the same HEAD_TITLE and the PAGE_TITLE is page specific:
<html>
<head><title>HEAD_TITLE</title></head>
<body>
<h1>PAGE_TITLE</h1>
</body>
</html>
This is a major usability problem as the browsers history lists all different pages of the application with the same title. The reason why the HEAD_TITLE is same for all pages is that I haven't found a reasonable way to use the PAGE_TITLE as the HEAD_TITLE.
In most cases the PAGE_TITLE comes from a message bundle with <fmt:message /> tag and
some parameters are passed to it. The Tiles layout is such that the HEAD_TITLE should be already set at that point because all pages of the webapp use the same common layout which defines the <HEAD> elements of the pages amongst other stuff.
Any suggestions how to fix this usability problem? Should I set a "pageTitle" request attribute in my Spring controllers for all pages and use that as the PAGE_TITLE and also as the HEAD_TITLE? Or is it possible to somehow set the HEAD_TITLE in the page specific JSP?
Create a general definition and define headTitle and pageTitle attributes.
<definition name="threeColumnLayout" template="/WEB-INF/ThreeColumnLayout.jsp" >
<put-attribute name="headTitle" value="" />
<put-attribute name="pageTitle" value="" />
<put-attribute name="left" value="/WEB-INF/left.jsp" />
<put-attribute name="middle" value="" />
<put-attribute name="right" value="/WEB-INF/right.jsp" />
</definition>
Set appropriate values in more specific definition.
<definition name="/user/new" extends="threeColumnLayout">
<put-attribute name="headTitle" value="Administration" />
<put-attribute name="pageTitle" value="Create User" />
<put-attribute name="middle" value="WEB-INF/views/UserCreate.jsp" />
</definition>
Use <tiles:getAsString /> tag to retrieve such values in jsp page.
<head>
<title><tiles:getAsString name="headTitle"/></title>
</head>
<body>
<h1>
<title><tiles:getAsString name="pageTitle"/></title>
</h1>
</body>
Reference:- http://tiles.apache.org/framework/tiles-jsp/tagreference.html#tiles:getAsString