blob: f171e92f93fe60384dbd3924d8525ab1e154c926 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Creating layouts using markup inheritance | Apache Wicket</title>
<meta charset="utf8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="shortcut icon" href="/favicon.ico" type="image/vnd.microsoft.icon" />
<link rel="stylesheet" href="/css/style.css" type="text/css" media="screen" />
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
</head>
<body class="">
<div class="header default">
<div class="l-container">
<nav class="mainmenu">
<ul>
<!-- /start/quickstart.html || /learn/examples/markupinheritance.html -->
<li class=""><a href="/start/quickstart.html">Quick Start</a></li>
<!-- /start/download.html || /learn/examples/markupinheritance.html -->
<li class=""><a href="/start/download.html">Download</a></li>
<!-- /learn || /learn/examples/markupinheritance.html -->
<li class=""><a href="/learn">Documentation</a></li>
<!-- /help || /learn/examples/markupinheritance.html -->
<li class=""><a href="/help">Support</a></li>
<!-- /contribute || /learn/examples/markupinheritance.html -->
<li class=""><a href="/contribute">Contribute</a></li>
<!-- /apache || /learn/examples/markupinheritance.html -->
<li class=""><a href="/apache">Apache</a></li>
</ul>
</nav>
<div class="logo">
<a href="/"><img src="/img/logo-apachewicket-white.svg" alt="Apache Wicket"></a>
</div>
</div>
</div>
<main>
<div class="l-container">
<header class="l-full preamble">
<h1>Creating layouts using markup inheritance</h1>
</header>
<section class="l-one-third right">
<div id="toc" class="toc"><div id="toc-title"><h2>Table of Contents</h2></div><ul><li class="toc--level-1 toc--section-1"><a href="#page-layout"><span class="toc-number">1</span> <span class="toc-text">Page layout</span></a></li><li class="toc--level-1 toc--section-2"><a href="#what-is-markup-inheritance"><span class="toc-number">2</span> <span class="toc-text">What is markup inheritance?</span></a></li><li class="toc--level-1 toc--section-3"><a href="#implementing-the-basepage"><span class="toc-number">3</span> <span class="toc-text">Implementing the BasePage</span></a></li><li class="toc--level-1 toc--section-4"><a href="#implementing-the-sub-pages"><span class="toc-number">4</span> <span class="toc-text">Implementing the sub pages</span></a></li><li class="toc--level-1 toc--section-5"><a href="#conclusion"><span class="toc-number">5</span> <span class="toc-text">Conclusion</span></a></li></ul></div>
</section>
<section class="l-two-third left">
<p>This markup inheritance example show you how to create reusable page layouts
and panel layouts.</p>
<p><a href="http://wicket.apache.org/screencasts/ApacheWicket_MarkupInheritence.avi">Watch the Screencast</a></p>
<p>In all the Wicket examples, you have to put all files in the same package
directory. This means putting the markup files and the java files next to one
another. It is possible to alter this behavior, but that is beyond the scope
of this example. The only exception is the obligatory <code>web.xml</code> file which
should reside in the <code>WEB-INF/</code> directory of your web application root
folder.</p>
<p>In this example we assume you already have read and understood the other
examples which give you information on the structure and nature of Wicket
applications. Specifically read and understand the <a href="helloworld.html">Hello, World
example</a>.</p>
<h2 id="page-layout">Page layout</h2>
<p>In the next figure we show a standard strategy for laying out a page. A
standard header, the main content body and a standard footer.</p>
<p><img src="markupinheritance1.png" alt="Markup inheritance diagram" /></p>
<p>In Wicket you can achieve this using different strategies. This article
focuses on one strategy: markup inheritance.</p>
<h2 id="what-is-markup-inheritance">What is markup inheritance?</h2>
<p>In Java you can extend classes. This same concept has been fitted into the
markup parsing of Java. Markup containers that have files associated (page
and panels) can inherit the markup of their super containers.</p>
<p>This is done using two special Wicket tags: <code>&lt;wicket:child&gt;</code> and
<code>&lt;wicket:extend&gt;</code>. In the super markup you define where the child markup
should be put, and in the sub markup you delineate where the child markup
starts and ends.</p>
<div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;html&gt;</span>
<span class="nt">&lt;head&gt;&lt;/head&gt;</span>
<span class="nt">&lt;body&gt;</span>
This is in the super markup.<span class="nt">&lt;br&gt;</span>
<span class="nt">&lt;wicket:child</span> <span class="nt">/&gt;</span>
This is in the super markup.<span class="nt">&lt;br&gt;</span>
<span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span></code></pre></div>
<p>In this markup you see two sentences that surround the <code>&lt;wicket:child&gt;</code> tag.
All markup in this file will remain when a sub class of this page is created,
only the <code>&lt;wicket:child&gt;</code> tag will be replaced with the child markup. So if we
look at the following markup:</p>
<div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;html&gt;</span>
<span class="nt">&lt;head&gt;&lt;/head&gt;</span>
<span class="nt">&lt;body&gt;</span>
This is in de child markup.<span class="nt">&lt;br&gt;</span>
<span class="nt">&lt;wicket:extend&gt;</span>
This is in the child markup.<span class="nt">&lt;br&gt;</span>
<span class="nt">&lt;/wicket:extend&gt;</span>
This is in the child markup.<span class="nt">&lt;br&gt;</span>
<span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span></code></pre></div>
<p>we can see the markup that should be included in the parent. Only the markup
between the <code>&lt;wicket:extend&gt;</code> tags is included in the final page. Take a look
at the following markup which is the final markup when you would use this in
a Wicket application.</p>
<div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;html&gt;</span>
<span class="nt">&lt;head&gt;&lt;/head&gt;</span>
<span class="nt">&lt;body&gt;</span>
This is in the super markup.<span class="nt">&lt;br&gt;</span>
<span class="nt">&lt;wicket:child&gt;&lt;wicket:extend&gt;</span>
This is in the child markup.<span class="nt">&lt;br&gt;</span>
<span class="nt">&lt;/wicket:extend&gt;&lt;/wicket:child&gt;</span>
This is in the super markup.<span class="nt">&lt;br&gt;</span>
<span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span></code></pre></div>
<p>Here you can see that the <code>&lt;wicket:child /&gt;</code> tag has been expanded, and its
contents filled with exactly the markup between the <code>&lt;wicket:extend&gt;</code> tags.
If you want to get rid of the special Wicket tags, you can disable that on
the markup settings
(<a href="http://wicketframework.org/api/wicket/settings/IMarkupSettings">IMarkupSettings</a>).</p>
<h2 id="implementing-the-basepage">Implementing the BasePage</h2>
<p>Now that we have seen the basics for markup inheritance, we can take a
look at the example at hand. Let’s first create the base page.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="n">wicket</span><span class="o">.</span><span class="na">quickstart</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">wicket.markup.html.WebPage</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">wicket.markup.html.basic.Label</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">wicket.markup.html.link.BookmarkablePageLink</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">abstract</span> <span class="kd">class</span> <span class="nc">BasePage</span> <span class="kd">extends</span> <span class="n">WebPage</span> <span class="o">{</span>
<span class="kd">public</span> <span class="nf">BasePage</span><span class="o">()</span> <span class="o">{</span>
<span class="n">add</span><span class="o">(</span><span class="k">new</span> <span class="nf">BookmarkablePageLink</span><span class="o">(</span><span class="s">&quot;page1&quot;</span><span class="o">,</span> <span class="n">Page1</span><span class="o">.</span><span class="na">class</span><span class="o">));</span>
<span class="n">add</span><span class="o">(</span><span class="k">new</span> <span class="nf">BookmarkablePageLink</span><span class="o">(</span><span class="s">&quot;page2&quot;</span><span class="o">,</span> <span class="n">Page2</span><span class="o">.</span><span class="na">class</span><span class="o">));</span>
<span class="n">add</span><span class="o">(</span><span class="k">new</span> <span class="nf">Label</span><span class="o">(</span><span class="s">&quot;footer&quot;</span><span class="o">,</span> <span class="s">&quot;This is in the footer&quot;</span><span class="o">));</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></div>
<p>The two links should go into the header, and the footer in the footer of the
page. Note that the abstract keyword isn’t required, but considered a good
practise. Now let’s take a look at the markup for the BasePage</p>
<div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;html&gt;</span>
<span class="nt">&lt;head&gt;&lt;/head&gt;</span>
<span class="nt">&lt;body&gt;</span>
<span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&quot;header&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;#&quot;</span> <span class="na">wicket:id=</span><span class="s">&quot;page1&quot;</span><span class="nt">&gt;</span>Page1<span class="nt">&lt;/a&gt;</span>
<span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;#&quot;</span> <span class="na">wicket:id=</span><span class="s">&quot;page2&quot;</span><span class="nt">&gt;</span>Page2<span class="nt">&lt;/a&gt;</span>
<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&quot;body&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;wicket:child</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&quot;footer&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;span</span> <span class="na">wicket:id=</span><span class="s">&quot;footer&quot;</span><span class="nt">&gt;&lt;/span&gt;</span>
<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span></code></pre></div>
<p>In this markup file you see the specific basic layout: we have 3 div
elements:</p>
<ol>
<li><code>&lt;div id="header"&gt;...&lt;/div&gt;</code></li>
<li><code>&lt;div id="body"&gt;...&lt;/div&gt;</code></li>
<li><code>&lt;div id="footer"&gt;...&lt;/div&gt;</code></li>
</ol>
<p>Note that these aren’t Wicket components, just plain markup. We could have
made them components, such as a <code>Panel</code> but for brevity we keep it this way.
Now that we have the <code>BasePage</code> finished, we can implement the two subclasses
to finish this example.</p>
<h2 id="implementing-the-sub-pages">Implementing the sub pages</h2>
<p>We need to build two pages: <code>Page1</code> and <code>Page2</code>. Each page needs its own
markup file and Java class. Let’s first implement <code>Page1</code>.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="n">wicket</span><span class="o">.</span><span class="na">quickstart</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">wicket.markup.html.basic.Label</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Page1</span> <span class="kd">extends</span> <span class="n">BasePage</span> <span class="o">{</span>
<span class="kd">public</span> <span class="nf">Page1</span><span class="o">()</span> <span class="o">{</span>
<span class="n">add</span><span class="o">(</span><span class="k">new</span> <span class="nf">Label</span><span class="o">(</span><span class="s">&quot;label1&quot;</span><span class="o">,</span> <span class="s">&quot;This is in the subclass Page1&quot;</span><span class="o">));</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></div>
<p>In this example you see that we add a new label component to the page:
<code>label1</code>. This component is only available for <code>Page1</code>, as such <code>Page2</code> can
define its own component hierarchy. Let’s take a look at the markup for
<code>Page1</code>:</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="o">&lt;</span><span class="n">html</span><span class="o">&gt;</span>
<span class="o">&lt;</span><span class="n">head</span><span class="o">&gt;&lt;/</span><span class="n">head</span><span class="o">&gt;</span>
<span class="o">&lt;</span><span class="n">body</span><span class="o">&gt;</span>
<span class="o">&lt;</span><span class="nl">wicket:</span><span class="n">extend</span><span class="o">&gt;</span>
<span class="o">&lt;</span><span class="n">h1</span><span class="o">&gt;</span><span class="n">Page1</span><span class="o">&lt;/</span><span class="n">h1</span><span class="o">&gt;</span>
<span class="o">&lt;</span><span class="n">span</span> <span class="nl">wicket:</span><span class="n">id</span><span class="o">=</span><span class="s">&quot;label1&quot;</span><span class="o">&gt;&lt;/</span><span class="n">span</span><span class="o">&gt;</span>
<span class="o">&lt;/</span><span class="nl">wicket:</span><span class="n">extend</span><span class="o">&gt;</span>
<span class="o">&lt;/</span><span class="n">body</span><span class="o">&gt;</span>
<span class="o">&lt;/</span><span class="n">html</span><span class="o">&gt;</span></code></pre></div>
<p>Here you see that we added the <code>Label</code> component in the markup between the
<code>&lt;wicket:extend&gt;</code> tags. If we were to add the component outside those tags,
Wicket will not be able to render the component in the final page.</p>
<p>Now, let’s do the same for <code>Page2</code>.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="n">wicket</span><span class="o">.</span><span class="na">quickstart</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">wicket.markup.html.basic.Label</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Page2</span> <span class="kd">extends</span> <span class="n">BasePage</span> <span class="o">{</span>
<span class="kd">public</span> <span class="nf">Page2</span><span class="o">()</span> <span class="o">{</span>
<span class="n">add</span><span class="o">(</span><span class="k">new</span> <span class="nf">Label</span><span class="o">(</span><span class="s">&quot;label2&quot;</span><span class="o">,</span> <span class="s">&quot;This is in the subclass Page2&quot;</span><span class="o">));</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></div>
<div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;html&gt;</span>
<span class="nt">&lt;head&gt;&lt;/head&gt;</span>
<span class="nt">&lt;body&gt;</span>
<span class="nt">&lt;wicket:extend&gt;</span>
<span class="nt">&lt;h1&gt;</span>Page2<span class="nt">&lt;/h1&gt;</span>
<span class="nt">&lt;span</span> <span class="na">wicket:id=</span><span class="s">&quot;label2&quot;</span><span class="nt">&gt;&lt;/span&gt;</span>
<span class="nt">&lt;/wicket:extend&gt;</span>
<span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span></code></pre></div>
<p>In <code>Page2</code> you see that we have a different component structure (<code>label2</code>
instead of <code>label1</code>), and as such that the pages are quite different.</p>
<p>If you paste this code into a Wicket quickstart application, you can see it
immediately working (don’t forget to set the homepage to <code>Page1</code> or <code>Page2</code>).</p>
<h2 id="conclusion">Conclusion</h2>
<p>With markup inheritance you can get a standard layout for your application
without too much hassle. It follows the natural inheritance strategy for Java
code and makes encapsulation of your component hierarchy possible.</p>
<p>In this example we haven’t touched on the other possible features of markup
inheritance:</p>
<ul>
<li>contributing to the <code>&lt;head&gt;</code> section from your sub pages</li>
<li>multiple layers of inheritance (this just works)</li>
<li>markup inheritance used with <code>Panel</code> components</li>
</ul>
<p>However, this example should get you up and running.</p>
</section>
</div>
</main>
<footer class="l-container">
<div class="l-full">
<img height="60px" src="/img/asf_logo.gif" style="float:left">
Copyright © 2014 — The Apache Software Foundation. Apache Wicket,
Wicket, Apache, the Apache feather logo, and the Apache Wicket
project logo are trademarks of The Apache Software Foundation. All
other marks mentioned may be trademarks or registered trademarks of
their respective owners.
</div>
</footer>
</body>
</html>