Appearance
Advanced Topics
We've already covered the foundations of Press: pages, frames, flows, styles, data, and page definitions. In this section, we'll introduce three features that unlock the real power of Press: conditional rendering, repeating over data, and components.
We'll continue building our AI history document from the previous sections.
Conditional Rendering
Sometimes you want to show a section only when certain data is present. Press supports this with the show-if attribute, which can be added to any element.
Let's add an optional author biography to our document. It should only appear when a biography has been provided in the data:
xml
<frame show-if="data.bio">
<h2>About the Author</h2>
<p>{{ data.bio }}</p>
</frame>If data.bio is present and non-empty, the frame will be rendered. If it's absent or empty, the frame is skipped entirely -- it won't take up any space.
You can use show-if on any element: frames, paragraphs, images, table rows, even entire pages:
xml
<img show-if="data.author-photo" src="{{ data.author-photo }}" />You can also use ternary expressions inside {{ }} to switch between values based on conditions:
xml
<frame width="{{ data.has-sidebar ? '60%' : '100%' }}">
<flow name="body" />
</frame>Repeating Over Data
In the previous sections, we manually wrote out our milestones list in the flow. But what if the milestones came from data? The <repeat> directive lets you iterate over an array and render elements for each item.
First, let's move the milestones into our <data> tag:
xml
<data type="json">
{
"title": "A History of Artificial Intelligence",
"author": "Mr P. Mill",
"milestones": [
{ "year": "1950", "event": "Turing Test proposed" },
{ "year": "1956", "event": "Dartmouth Conference" },
{ "year": "1980", "event": "Expert systems boom" },
{ "year": "2012", "event": "Deep learning revolution" }
]
}
</data>Now we can generate the list from data:
xml
<h2>Key Milestones</h2>
<table>
<tr>
<th>Year</th>
<th>Event</th>
</tr>
<repeat data="data.milestones" item="milestone">
<tr>
<td>{{ milestone.year }}</td>
<td>{{ milestone.event }}</td>
</tr>
</repeat>
</table>The <repeat> tag takes two attributes:
data-- the array to loop overitem-- the variable name for each element (defaults toitem)
You can nest repeats, and use show-if inside them:
xml
<repeat data="data.milestones" item="milestone">
<frame>
<h3>{{ milestone.year }} - {{ milestone.event }}</h3>
<p show-if="milestone.description">{{ milestone.description }}</p>
</frame>
</repeat>Components
As templates grow, you'll find yourself repeating patterns. Components let you define reusable elements with their own structure and accept inputs via attributes and slots.
Let's create a component for the header we've been using on our left and right pages:
xml
<components>
<page-header text="">
<frame width="100%" margin-bottom="0.5cm" font-color="grey"
text-align="{{ attrs.align ? attrs.align : 'left' }}">
{{ attrs.text }}
</frame>
</page-header>
</components>Now our page definitions become simpler:
xml
<pages>
<left-page>
<page-header text="{{ data.author }}" align="right" />
<flow name="body" />
</left-page>
<right-page>
<page-header text="{{ data.title }}" />
<flow name="body" />
</right-page>
</pages>Components accept attributes through {{ attrs.attribute-name }}. You can set defaults in the component definition -- here, text defaults to an empty string.
Slots
For components that wrap other content, use <slot /> as a placeholder:
xml
<components>
<info-box title="" background="#f0f0f0">
<frame background-color="{{ attrs.background }}" padding="12pt"
border-radius="4pt">
<h3>{{ attrs.title }}</h3>
<slot />
</frame>
</info-box>
</components>Then use it anywhere in your document:
xml
<info-box title="Did You Know?" background="#e8f4e8">
<p>The term "Artificial Intelligence" was coined at the
Dartmouth Conference in 1956.</p>
</info-box>Whatever you place inside the <info-box> tags replaces the <slot /> in the component definition.
Putting It All Together
Here's our AI history document with all three features added:
xml
<press>
<document width="14.8cm" height="21cm" page-margin="1cm">
<coverpage />
<repeat flow="body">
<left-page />
<right-page />
</repeat>
</document>
<pages>
<coverpage>
<frame left="1cm" width="10cm">
<h1 font-size="fit">{{ data.title }}</h1>
</frame>
<frame left="1cm" top="15cm">
<h2>{{ data.author }}</h2>
</frame>
</coverpage>
<left-page>
<page-header text="{{ data.author }}" align="right" />
<flow name="body" />
</left-page>
<right-page>
<page-header text="{{ data.title }}" />
<flow name="body" />
</right-page>
</pages>
<flows>
<body>
<h1>{{ data.title }}</h1>
<h2>Key Milestones</h2>
<table>
<tr>
<th>Year</th>
<th>Event</th>
</tr>
<repeat data="data.milestones" item="milestone">
<tr>
<td>{{ milestone.year }}</td>
<td>{{ milestone.event }}</td>
</tr>
</repeat>
</table>
<h2>AI Domains</h2>
<ul>
<repeat data="data.domains" item="domain">
<li>{{ domain }}</li>
</repeat>
</ul>
<info-box title="Looking Forward" show-if="data.conclusion">
<p>{{ data.conclusion }}</p>
</info-box>
<frame show-if="data.bio">
<h2>About the Author</h2>
<p>{{ data.bio }}</p>
</frame>
</body>
</flows>
<components>
<page-header text="" align="left">
<frame width="100%" margin-bottom="0.5cm" font-color="grey"
text-align="{{ attrs.align }}">
{{ attrs.text }}
</frame>
</page-header>
<info-box title="" background="#f0f0f0">
<frame background-color="{{ attrs.background }}" padding="12pt"
border-radius="4pt">
<h3>{{ attrs.title }}</h3>
<slot />
</frame>
</info-box>
</components>
<styles>
<h1>
<font-color>grey</font-color>
</h1>
</styles>
<data type="json">
{
"title": "A History of Artificial Intelligence",
"author": "Mr P. Mill",
"milestones": [
{ "year": "1950", "event": "Turing Test proposed" },
{ "year": "1956", "event": "Dartmouth Conference" },
{ "year": "1980", "event": "Expert systems boom" },
{ "year": "2012", "event": "Deep learning revolution" }
],
"domains": [
"Machine Learning",
"Natural Language Processing",
"Computer Vision",
"Robotics"
],
"conclusion": "As we stand at the threshold of artificial general intelligence, the next decade promises even more dramatic changes.",
"bio": "Mr P. Mill is a researcher in artificial intelligence and the author of several papers on the history of computing."
}
</data>
</press>We now have a fully data-driven, conditionally rendered, component-based document. Try removing bio or conclusion from the data to see those sections disappear.
The rest of this documentation covers each of these features -- and many more -- in depth. Head to the Guides section for comprehensive coverage of any topic, or check the Reference section when you need to look up a specific attribute or element.