Nested templates with tiles - spring-mvc

I want to have some nested templates with tiles, but without any luck for the moment.
My main template :
[...]
<div id=body><tiles:insertAttribute name="body"/></div>
[...]
My nested template:
[...]
<div id=sub><tiles:insertAttribute name="sub"/></div>
[...]
My view definition:
<tiles-definitions>
<definition name="mainTemplate" template="/mainTemplate.jspx">
</definition>
<definition extends="mainTemplate" name="subTemplate">
<put-attribute name="body" value="/subTemplate.jspx"/>
</definition>
<definition extends="mainTemplate" name="myView">
<put-attribute name="sub" value="blablabla"/>
</definition>
</tiles-definitions>
What I expected :
<div id=body><div id=sub>blablabla</div></div>
What I got :
<div id=body><div id=sub></div></div>
I have seen the documentation on the tiles website about this subject but I can't make it work :(

Actually, "subTemplate" and "myView" are two different definitions extending "mainTemplate" both. From what I understand you want the"myView" tile to be nested inside the "subTemplate" tile.
You could try something like this :
<tiles-definitions>
<definition name="mainTemplate" template="/mainTemplate.jspx">
<definition name="subTemplate" extends="mainTemplate">
<put-attribute name="body">
<definition template="/subTemplate.jspx">
<put-attribute name="myView" value="blablabla" />
</definition>
</put-attribute>
</definition>
</tiles-definition>

Related

Tiles 3 how to reference another definition in put-attribute

I'd like to be able to define a base definition, where I can inherit a list of styles and scripts. then define a page definition that inherits base definition, and adds page specific styles and scripts. Is this possible -or am I not thinking about this in the right way? I would have thought this to be a fairly basic idea.
base definitions
<tiles-definitions>
<!-- base styles -->
<definition name="base.styles" >
<put-list-attribute name="styles" cascade="true" >
<add-attribute value="/view/common/jquery-ui-theme-base-v1.12.1.css" />
</put-list-attribute>
</definition>
<!-- base scripts -->
<definition name="base.scripts" >
<put-list-attribute name="scripts" cascade="true" >
<add-attribute value="https://code.jquery.com/jquery-3.1.0.min.js" />
<add-attribute value="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" />
</put-list-attribute>
</definition>
<!-- base definition -->
<definition name="base.definition" template="/WEB-INF/page/defaultLayout.jsp" >
<put-attribute name="title" />
<put-attribute name="styles" value="base.styles.styles" cascade="true" />
<put-attribute name="header" value="/WEB-INF/page/common/header.jsp" />
<put-attribute name="body" />
<put-attribute name="scripts" value="base.scripts.scripts" cascade="true" />
<put-attribute name="footer" value="/WEB-INF/page/common/footer.jsp" />
</definition>
</tiles-definitions>
note the values of the put-attribute match the names of the definitions above them. (my guess is this isn't correct)
page specific definitions
<tiles-definitions>
<!-- page specific styles -->
<definition name="samplePage.styles" extends="base.styles" >
<put-list-attribute name="styles" inherit="true" >
<add-attribute value="/view/page/samplePage/samplePageStyles.css" />
</put-list-attribute>
</definition>
<!-- page specific scripts -->
<definition name="samplePage.scripts" extends="base.scripts" >
<put-list-attribute name="scripts" inherit="true" >
<add-attribute value="/view/page/samplePage/samplePageScript.js" />
</put-list-attribute>
</definition>
<!-- page specific definition -->
<definition name="samplePage" extends="base.definition" >
<put-attribute name="title" value="Sample Page" />
<put-attribute name="styles" value="samplePage.styles" cascade="true" />
<put-attribute name="body" value="/WEB-INF/page/samplePage/samplePageBody" />
<put-attribute name="scripts" value="samplePage.scripts" cascade="true" />
</definition>
</tiles-definitions>
again -note the values of the put-attribute match the names of the definitions above them. (probably not correct?)
I'm currently getting an IllegalArgumentException
Caused by: java.lang.IllegalArgumentException: Cannot convert samplePage.styles of type class java.lang.String to class org.apache.tiles.Attribute
at com.sun.el.lang.ELSupport.coerceToType(ELSupport.java:428)
at com.sun.el.ExpressionFactoryImpl.coerceToType(ExpressionFactoryImpl.java:85)
... 104 more
It appears as if the put-attributes for the styles and scripts are not picking up the definitions of the same name above them... but I'm not sure what to do to correct it. Any ideas?
To answer the question how to reference another definition in put-attribute, this appears to be fairly easy with jsp components such as the following (note the definition, and the 'type' attribute):
<definition name="default.header" template="/WEB-INF/page/common/header.jsp" />
... then elsewhere...
<put-attribute name="header" type="definition" value="default.header" />
However, it doesn't look like this can be done with resources such as stylesheets and scripts, as they don't translate back to an actual template. So, I reworked my base-definition as follows, which still allows me to have 'global' resources, as well as 'page-specific' resources. Also allows me to write the jsp components once, define them once, and reference them many times.
common definitions (tiles.common.xml)
<tiles-definitions>
<definition name="default.header" template="/WEB-INF/page/common/header.jsp" />
<definition name="default.footer" template="/WEB-INF/page/common/footer.jsp" />
[... all the other common components...]
</tiles-definitions>
base definition (tiles.base.xml)
<tiles-definitions>
<definition name="base.definition" template="/WEB-INF/page/baseLayout.jsp" >
<put-attribute name="title" type="string" />
<put-attribute name="header" type="definition" value="default.header" />
<put-attribute name="body" />
<put-attribute name="footer" type="definition" value="default.footer" />
<put-list-attribute name="styles" inherit="true" >
<add-attribute value="/view/common/jquery-ui-theme-base-v1.12.1.css" />
[... other styles common to all pages...]
</put-list-attribute>
<put-list-attribute name="scripts" inherit="true" >
<add-attribute value="https://code.jquery.com/jquery-3.1.0.min.js" />
<add-attribute value="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" />
[... other scripts common to all pages...]
</put-list-attribute>
</definition>
</tiles-definition>
page specific definition (tiles.samplePage.xml)
<tiles-definitions>
<definition name="samplePage" extends="base.definition" >
<put-attribute name="title" value="Sample Page" />
<put-attribute name="body" value="/WEB-INF/page/samplePage.jsp" />
<put-list-attribute name="styles" inherit="true" >
<add-attribute value="/view/pages/samplePage.css" />
[... other page specific styles ...]
</put-list-attribute>
<put-list-attribute name="scripts" inherit="true" >
<add-attribute value="/view/pages/samplePage.js" />
[... other page specific scripts ...]
</put-list-attribute>
</definition>
</tiles-definition>

tiles 2.1: nesting templates 3 levels deep - attribute isn't replaced

I see PLACEHOLDER on result page instead of edit.jsp page content. Source of tiles-defs.xml listed below.
<definition name="layout" template="/WEB-INF/tiles/layout.jsp">
<put-attribute name="body">
<definition template="/WEB-INF/tiles/user/layout.jsp">
<put-attribute name="userMenu" value="/WEB-INF/tiles/user/menu.jsp"/>
<put-attribute name="userContent">
<definition template="/WEB-INF/tiles/user/profile/layout.jsp">
<put-attribute name="profileNav" value="/WEB-INF/tiles/user/profile/nav.jsp"/>
<put-attribute name="profileContent" value="PLACEHOLDER"/>
</definition>
</put-attribute>
</definition>
</put-attribute>
...
</definition>
<definition name="editUser" extends="layout">
<put-attribute name="profileContent" value="/WEB-INF/jsp/user/auth/edit.jsp"/>
...
</definition>
Also tried to split in 3 separate definitions without any result. Also played with cascade attribute without any result too.
Pls. add to top of /WEB-INF/tiles/user/profile/layout.jsp:
<%#taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>

Get spring.profiles.active in Tiles.xml

Can we recover the active profile in tiles.xml?
I need to display an indicator in the title of the active profile.
web.xml
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>QA</param-value>
</context-param>
Tiles.xml
<definition name="base.layout" template="/WEB-INF/views/layout/layout.jsp">
<put-attribute name="title" value="My title - GET PROFILE ACTIVE HERE" />
<put-attribute name="header" value="/WEB-INF/views/layout/header.jsp" />
<put-attribute name="contentLayout" value="" />
<put-attribute name="footer" value="/WEB-INF/views/layout/footer.jsp" />
</definition>
Why don't you use app.properties as follows?
spring.profiles.active=QA
then in your xml you can use:
<util:properties id="app.properties" location="classpath:application.properties"/>
<definition name="base.layout" template="/WEB-INF/views/layout/layout.jsp">
<put-attribute name="title" value="${spring.profiles.active}"/>
...
</definition>

Use properties file inside Apache Tiles 2 config file

I'm using Spring MVC 3 + Apache Tile 2.2 and I was just wondering if I could use properties directly from tiles-def.xml file. So my tiles-def looks like:
<definition name=".mainTemplate" extends=".client1MainTemplate">
<put-attribute name="title" value="Title1" type="string" />
</definition>
and I'd like to put the value of the Title into the messages.properties file instead of putting it here. Any way of doing it?
Cheers
I would do something like this:
<definition name="*" extends=".mainTemplate">
<put-attribute name="viewName" value="{1}"/>
<put-attribute name="body" value="/WEB-INF/views/{1}.jsp" />
</definition>
and in your template file:
<tiles:importAttribute name="viewName"/>
<title><spring:message code="${viewName}.title"/></title>
For a view name "index", this would look for "index.title" in messages.properties.

How to automate body import with Apache Tiles and Spring MVC

I have the following tiles-def.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>
<definition name="default" template="/WEB-INF/jsp/layout.jsp">
<put-attribute name="title" value="my webapp" />
<put-attribute name="header" value="/WEB-INF/jsp/header.jsp" />
<put-attribute name="menu" value="/WEB-INF/jsp/menu.jsp" />
<put-attribute name="body" value="/WEB-INF/jsp/hello.jsp" />
<put-attribute name="footer" value="/WEB-INF/jsp/footer.jsp" />
</definition>
<definition name="contact" extends="default">
<put-attribute name="body" value="/WEB-INF/jsp/contact.jsp" />
</definition>
<definition name="hello" extends="default">
<put-attribute name="body" value="/WEB-INF/jsp/hello.jsp" />
</definition>
</tiles-definitions>
As you can see, in all my pages, just the body changes. Is there a way to automate this? (so it automatically includes the jsp that has the name of the requested page, or an error page if it doesnt exist?)
Thank you!
EDIT: More details of what I want to do:
How it is now:
For each new page of my webapp, I have to add a new to my tiles-def.xml. And everytime, the only thing it does is setting the body with my content page.
What I would like to do:
Just have one default definition that automatically chose the page to display, something like this:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>
<definition name="default" template="/WEB-INF/jsp/layout.jsp">
<put-attribute name="title" value="my webapp" />
<put-attribute name="header" value="/WEB-INF/jsp/header.jsp" />
<put-attribute name="menu" value="/WEB-INF/jsp/menu.jsp" />
if(myPageName exists){
<put-attribute name="body" value="/WEB-INF/jsp/" + myPageName + ".jsp" />
else{
<put-attribute name="body" value="/WEB-INF/jsp/error404.jsp" />
}
<put-attribute name="footer" value="/WEB-INF/jsp/footer.jsp" />
</definition>
</tiles-definitions>
Where myPageName would be the name of the page requested (If the URL was "http://www.mysite.com/contact.html", then myPageName would be "contact". If it was "http://www.mysite.com/info.html", then myPageName would be "info").
How can I do this?
Check out the Dynamic Tiles Example on the springbyexample.org page. The DynamicTilesView does exactly what you want (see example config here). The full Dynamic Tiles Example can be found here on github

Resources