blob: e622249c97e36e93f0a5c43cd29dbb7745664a02 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="Date-Revision-yyyymmdd" content="20140918"/>
<meta http-equiv="Content-Language" content="en"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Tag Developers Guide</title>
<link href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,400italic,600italic,700italic" rel="stylesheet" type="text/css">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<link href="/css/main.css" rel="stylesheet">
<link href="/css/custom.css" rel="stylesheet">
<link href="/css/syntax.css" rel="stylesheet">
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="/bootstrap/js/bootstrap.js"></script>
<script type="text/javascript" src="/js/community.js"></script>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/* We explicitly disable cookie tracking to avoid privacy issues */
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '41']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body>
<a href="https://github.com/apache/struts" class="github-ribbon">
<img decoding="async" loading="lazy" style="position: absolute; right: 0; border: 0;" width="149" height="149" src="https://github.blog/wp-content/uploads/2008/12/forkme_right_red_aa0000.png?resize=149%2C149" class="attachment-full size-full" alt="Fork me on GitHub" data-recalc-dims="1">
</a>
<header>
<nav>
<div role="navigation" class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" data-toggle="collapse" data-target="#struts-menu" class="navbar-toggle">
Menu
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="/index.html" class="navbar-brand logo"><img src="/img/struts-logo.svg"></a>
</div>
<div id="struts-menu" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Home<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/index.html">Welcome</a></li>
<li><a href="/download.cgi">Download</a></li>
<li><a href="/releases.html">Releases</a></li>
<li><a href="/announce-2024.html">Announcements</a></li>
<li><a href="http://www.apache.org/licenses/">License</a></li>
<li><a href="https://www.apache.org/foundation/thanks.html">Thanks!</a></li>
<li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy Policy</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Support<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/mail.html">User Mailing List</a></li>
<li><a href="https://issues.apache.org/jira/browse/WW">Issue Tracker</a></li>
<li><a href="/security.html">Reporting Security Issues</a></li>
<li><a href="/commercial-support.html">Commercial Support</a></li>
<li class="divider"></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Migration+Guide">Version Notes</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Security+Bulletins">Security Bulletins</a></li>
<li class="divider"></li>
<li><a href="/maven/project-info.html">Maven Project Info</a></li>
<li><a href="/maven/struts2-core/dependencies.html">Struts Core Dependencies</a></li>
<li><a href="/maven/struts2-plugins/modules.html">Plugin Dependencies</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Documentation<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/birdseye.html">Birds Eye</a></li>
<li><a href="/primer.html">Key Technologies</a></li>
<li><a href="/kickstart.html">Kickstart FAQ</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Home">Wiki</a></li>
<li class="divider"></li>
<li><a href="/getting-started/">Getting Started</a></li>
<li><a href="/security/">Security Guide</a></li>
<li><a href="/core-developers/">Core Developers Guide</a></li>
<li><a href="/tag-developers/">Tag Developers Guide</a></li>
<li><a href="/maven-archetypes/">Maven Archetypes</a></li>
<li><a href="/plugins/">Plugins</a></li>
<li><a href="/maven/struts2-core/apidocs/index.html">Struts Core API</a></li>
<li><a href="/tag-developers/tag-reference.html">Tag reference</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/FAQs">FAQs</a></li>
<li><a href="http://cwiki.apache.org/S2PLUGINS/home.html">Plugin registry</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Contributing<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/youatstruts.html">You at Struts</a></li>
<li><a href="/helping.html">How to Help FAQ</a></li>
<li><a href="/dev-mail.html">Development Lists</a></li>
<li class="divider"></li>
<li><a href="/submitting-patches.html">Submitting patches</a></li>
<li><a href="/builds.html">Source Code and Builds</a></li>
<li><a href="/coding-standards.html">Coding standards</a></li>
<li><a href="/contributors/">Contributors Guide</a></li>
<li class="divider"></li>
<li><a href="/release-guidelines.html">Release Guidelines</a></li>
<li><a href="/bylaws.html">PMC Charter</a></li>
<li><a href="/volunteers.html">Volunteers</a></li>
<li><a href="https://gitbox.apache.org/repos/asf?p=struts.git">Source Repository</a></li>
<li><a href="/updating-website.html">Updating the website</a></li>
</ul>
</li>
<li class="apache"><a href="http://www.apache.org/"><img src="/img/apache.png"></a></li>
</ul>
</div>
</div>
</div>
</nav>
</header>
<article class="container">
<section class="col-md-12">
<a class="edit-on-gh" href="https://github.com/apache/struts-site/edit/master/source/tag-developers/template-loading.md" title="Edit this page on GitHub">Edit on GitHub</a>
<h1 class="no_toc" id="template-loading">Template Loading</h1>
<ul id="markdown-toc">
<li><a href="#template-and-themes" id="markdown-toc-template-and-themes">Template and Themes</a></li>
<li><a href="#overriding-templates" id="markdown-toc-overriding-templates">Overriding Templates</a></li>
<li><a href="#altering-template-loading-behaviour" id="markdown-toc-altering-template-loading-behaviour">Altering Template Loading Behaviour</a></li>
<li><a href="#alternative-template-engines" id="markdown-toc-alternative-template-engines">Alternative Template Engines</a></li>
</ul>
<p>Templates are loaded first by searching the application and then by searching the classpath. If a template needs to be
overridden, an edited copy can be placed in the application, so that is found first.</p>
<p><strong>One for all</strong></p>
<blockquote>
<p>FreeMarker is the default templating engine. The FreeMarker templates are used regardless of what format the view may
use. Internally, the JSP, FTL, Velocity tags are all rendered using FreeMarker.</p>
</blockquote>
<h2 id="template-and-themes">Template and Themes</h2>
<p>Templates are loaded based the template directory and theme name (see <a href="selecting-themes">Selecting Themes</a>).
The template directory is defined by the <code class="language-plaintext highlighter-rouge">struts.ui.templateDir</code> property in <code class="language-plaintext highlighter-rouge">struts.xml</code> (defaults to <code class="language-plaintext highlighter-rouge">template</code>).
If a tag is using the <code class="language-plaintext highlighter-rouge">xhtml</code> theme, the following two locations will be searched (in this order):</p>
<table>
<tbody>
<tr>
<td>In the application</td>
<td><code class="language-plaintext highlighter-rouge">/template/xhtml/template.ftl</code></td>
</tr>
<tr>
<td>In the classpath</td>
<td><code class="language-plaintext highlighter-rouge">/template/xhtml/template.ftl</code></td>
</tr>
</tbody>
</table>
<blockquote>
<p>For performance reasons, you may want to prefer the first location, although the second one is more flexible.
See <a href="../core-developers/performance-tuning">Performance Tuning</a> for a discussion on this topic.</p>
</blockquote>
<h2 id="overriding-templates">Overriding Templates</h2>
<p>The default templates provided in the <code class="language-plaintext highlighter-rouge">struts2-core.jar</code> should suit the needs of many applications. However,
if a template needs to be modified, it’s easy to plug in a new version. Extract the template you need to change from
the <code class="language-plaintext highlighter-rouge">struts2-core.jar</code>, make the modifications, and save the updated copy to <code class="language-plaintext highlighter-rouge">/template/$theme/$template.ftl</code>.
If you are using the <code class="language-plaintext highlighter-rouge">xhtml</code> theme and need to change how the select tags render, edit that template and save it to
<code class="language-plaintext highlighter-rouge">/template/xhtml/select.ftl</code>.</p>
<blockquote>
<p>It is easier and better to edit and override an existing template than provide a new one of your own.</p>
</blockquote>
<h2 id="altering-template-loading-behaviour">Altering Template Loading Behaviour</h2>
<p>It is possible to load template from other locations, like the file system or a URL. Loading templates from alternate
locations can be useful not only for tags, but for custom results. For details, see the <a href="freemarker">FreeMarker</a>
documentation and consult the section on extending the FreeMarkerManager.</p>
<h2 id="alternative-template-engines">Alternative Template Engines</h2>
<p>The framework provides for template rendering engines other than FreeMarker. (Though, there is rarely a need to use
another system!)</p>
<p><strong>Don’t try this at home!</strong></p>
<blockquote>
<p>Alternative template engines are best left to advanced users with special needs!</p>
</blockquote>
<p>The framework supports three template engines, which can be controlled by the <code class="language-plaintext highlighter-rouge">struts.ui.templateSuffix</code> in
<code class="language-plaintext highlighter-rouge">struts.xml</code>.</p>
<table>
<tbody>
<tr>
<td>ftl (default)</td>
<td><a href="freemarker">FreeMarker</a>-based template engine</td>
</tr>
<tr>
<td>vm</td>
<td><a href="velocity">Velocity</a>-based template engine</td>
</tr>
<tr>
<td>jsp</td>
<td><a href="jsp">JSP</a>-based template engine</td>
</tr>
</tbody>
</table>
<p>The only set of templates and themes provided in the distribution is for FreeMarker. In order to use another template
engine, you must provide your own template and theme for that engine.</p>
<blockquote>
<p>Don’t feel that you need to rewrite the templates to match your view format. If you need to customize the template,
try copying and modifying the FreeMarker template first. Most changes should be obvious.</p>
</blockquote>
</section>
</article>
<footer class="container">
<div class="col-md-12">
Copyright &copy; 2000-2022 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
Apache Struts, Struts, Apache, the Apache feather logo, and the Apache Struts project logos are
trademarks of The Apache Software Foundation. All Rights Reserved.
</div>
<div class="col-md-12">Logo and website design donated by <a href="https://softwaremill.com/">SoftwareMill</a>.</div>
</footer>
<script>!function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (!d.getElementById(id)) {
js = d.createElement(s);
js.id = id;
js.src = "//platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
}
}(document, "script", "twitter-wjs");</script>
<script src="https://apis.google.com/js/platform.js" async="async" defer="defer"></script>
<div id="fb-root"></div>
<script>(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s);
js.id = id;
js.src = "//connect.facebook.net/en_GB/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
</body>
</html>