blob: 647cfc5887adea541a7cd5b01fbe9ef5846c7294 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta charset="utf-8">
<title>Creating layouts using markup inheritance | Apache Wicket</title>
<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.7.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 -->
<li class=""><a href="/start/quickstart.html">Quick Start</a></li>
<!-- /start/download.html || /learn/examples/markupinheritance -->
<li class=""><a href="/start/download.html">Download</a></li>
<!-- /learn || /learn/examples/markupinheritance -->
<li class=""><a href="/learn">Documentation</a></li>
<!-- /help || /learn/examples/markupinheritance -->
<li class=""><a href="/help">Support</a></li>
<!-- /contribute || /learn/examples/markupinheritance -->
<li class=""><a href="/contribute">Contribute</a></li>
<!-- /community || /learn/examples/markupinheritance -->
<li class=""><a href="/community">Community</a></li>
<!-- /apache || /learn/examples/markupinheritance -->
<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>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 class="language-plaintext highlighter-rouge">web.xml</code> file which
should reside in the <code class="language-plaintext highlighter-rouge">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 class="language-plaintext highlighter-rouge">&lt;wicket:child&gt;</code> and
<code class="language-plaintext highlighter-rouge">&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>
<figure 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></figure>
<p>In this markup you see two sentences that surround the <code class="language-plaintext highlighter-rouge">&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 class="language-plaintext highlighter-rouge">&lt;wicket:child&gt;</code> tag will be replaced with the child markup. So if we
look at the following markup:</p>
<figure 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></figure>
<p>we can see the markup that should be included in the parent. Only the markup
between the <code class="language-plaintext highlighter-rouge">&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>
<figure 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></figure>
<p>Here you can see that the <code class="language-plaintext highlighter-rouge">&lt;wicket:child /&gt;</code> tag has been expanded, and its
contents filled with exactly the markup between the <code class="language-plaintext highlighter-rouge">&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
(see <a href="https://ci.apache.org/projects/wicket/apidocs/6.x/org/apache/wicket/settings/IMarkupSettings.html">IMarkupSettings</a> for Wikcet6
or <a href="https://ci.apache.org/projects/wicket/apidocs/7.x/org/apache/wicket/settings/MarkupSettings.html">MarkupSettings</a> for Wicket 7 or <a href="https://ci.apache.org/projects/wicket/apidocs/8.x/org/apache/wicket/settings/MarkupSettings.html">MarkupSettings</a> for Wicket 8).</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>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="nn">wicket.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="nc">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="nc">BookmarkablePageLink</span><span class="o">(</span><span class="s">"page1"</span><span class="o">,</span> <span class="nc">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="nc">BookmarkablePageLink</span><span class="o">(</span><span class="s">"page2"</span><span class="o">,</span> <span class="nc">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="nc">Label</span><span class="o">(</span><span class="s">"footer"</span><span class="o">,</span> <span class="s">"This is in the footer"</span><span class="o">));</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<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>
<figure 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">"header"</span><span class="nt">&gt;</span>
<span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"#"</span> <span class="na">wicket:id=</span><span class="s">"page1"</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">"#"</span> <span class="na">wicket:id=</span><span class="s">"page2"</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">"body"</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">"footer"</span><span class="nt">&gt;</span>
<span class="nt">&lt;span</span> <span class="na">wicket:id=</span><span class="s">"footer"</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></figure>
<p>In this markup file you see the specific basic layout: we have 3 div
elements:</p>
<ol>
<li><code class="language-plaintext highlighter-rouge">&lt;div id="header"&gt;...&lt;/div&gt;</code></li>
<li><code class="language-plaintext highlighter-rouge">&lt;div id="body"&gt;...&lt;/div&gt;</code></li>
<li><code class="language-plaintext highlighter-rouge">&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 class="language-plaintext highlighter-rouge">Panel</code> but for brevity we keep it this way.
Now that we have the <code class="language-plaintext highlighter-rouge">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 class="language-plaintext highlighter-rouge">Page1</code> and <code class="language-plaintext highlighter-rouge">Page2</code>. Each page needs its own
markup file and Java class. Let’s first implement <code class="language-plaintext highlighter-rouge">Page1</code>.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="nn">wicket.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="nc">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="nc">Label</span><span class="o">(</span><span class="s">"label1"</span><span class="o">,</span> <span class="s">"This is in the subclass Page1"</span><span class="o">));</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<p>In this example you see that we add a new label component to the page:
<code class="language-plaintext highlighter-rouge">label1</code>. This component is only available for <code class="language-plaintext highlighter-rouge">Page1</code>, as such <code class="language-plaintext highlighter-rouge">Page2</code> can
define its own component hierarchy. Let’s take a look at the markup for
<code class="language-plaintext highlighter-rouge">Page1</code>:</p>
<figure 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="nc">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">"label1"</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></figure>
<p>Here you see that we added the <code class="language-plaintext highlighter-rouge">Label</code> component in the markup between the
<code class="language-plaintext highlighter-rouge">&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 class="language-plaintext highlighter-rouge">Page2</code>.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="nn">wicket.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="nc">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="nc">Label</span><span class="o">(</span><span class="s">"label2"</span><span class="o">,</span> <span class="s">"This is in the subclass Page2"</span><span class="o">));</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<figure 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">"label2"</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></figure>
<p>In <code class="language-plaintext highlighter-rouge">Page2</code> you see that we have a different component structure (<code class="language-plaintext highlighter-rouge">label2</code>
instead of <code class="language-plaintext highlighter-rouge">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 class="language-plaintext highlighter-rouge">Page1</code> or <code class="language-plaintext highlighter-rouge">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 class="language-plaintext highlighter-rouge">&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 class="language-plaintext highlighter-rouge">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 src="/img/asf_logo_url.svg" style="height:90px; float:left; margin-right:10px;">
<div style="margin-top:12px;">Copyright © 2020 — 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>
</div>
</footer>
</body>
</html>