Každý článek chceme zařadit do vybrané kategorie. Kategorie si chceme volně editovat v administračním rozhraní. Potřebujeme tedy vytvořit kolekci kategorií a nějak určit, do které kategorie který článek náleží.
Datový typ reprezentující kategorii je jednoduchý – obsahuje jen název dané kategorie. Do Site.config přidáme:
...
<Type name="BlogPostCategoryItem">
<SimpleText name="title" />
</Type>
...
Kategorií bude přirozeně víc než jedna, ve <Vars> v Site.configtedy založíme jejich kolekci:
... <Collection name="blogPostCategory" itemType="BlogPostCategoryItem" /> ...
Teď ještě potřebujeme nějak propojit prvky ze seznamu kategorií s jednotlivými články. K tomu slouží pole typu <Reference>. Typ BlogPostItem z předchozí kapitoly upravíme takto:
...
<Type name="BlogPostItem">
<SimpleText name="title" />
<DateTime name="published" />
<Text name="text" />
<Reference name="category" sourceCol="blogPostCategory" />
</Type>
...
Atribut sourceCol určuje zdrojovou kolekci s kategoriemi článků, v našem případě jednoduše blogPostCategory.
Cestu ke kolekci jsem zadali tzv. absolutně, bez tečky na počátku. Prostě jsme do atributu sourceCol napsali jméno kolekce. V našem příkladu to ani jinak nejde. JellyPot ale obecně umožňuje cestu pro <Reference> určit i relativně, s tečkou na počátku. To se hodí u složitějších datových struktur, kdy máme obě kolekce v proměnné nebo dokonce kolekci a chceme se z vnořené kolekce odkazovat do té vnější. Více viz <Reference>.
Kdybychom chtěli jednomu článku přiřadit víc než jednou kategorii, použili bychom typ <ReferenceCollection>.
V administraci si naplňte pár kategorií a přiřaďte je článkům, ať máme na čem zkoušet následující.
.aspx šablona
Kromě datového modelu musíme upravit i .aspx pro konkrétní článek – chceme v něm vypsat i jeho kategorii. Nakonec přidáme stránku s přehledem článků dané kategorie.
Stránky s článkem
Upravíme stránku /cs/blogpost.aspx, kterou jsme vytvořili v kapitole Blog za 5 minut.
<%@ Page %>
<je:container runat="server" expect="blogPost">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<je:stylelink runat="server" href="/assets/css/main.css" />
<title><je:item runat="server" field=".title" /></title>
</head>
<body>
<header>
<je:a runat="server" class="logo" href="/cs/">Můj blog</je:a>
<nav>
<je:a runat="server" href="/cs/">Homepage</je:a>
<je:a runat="server" href="/cs/about.aspx">O autorovi</je:a>
</nav>
</header>
<main>
<je:item runat="server" field=".title" tag="h1" />
<je:item runat="server" field=".published" tag="time" />
<je:avar runat="server" href="category.aspx" container=".category">
<je:item runat="server" field=".category.title" />
</je:avar>
<je:item runat="server" field=".text" />
</main>
</body>
</html>
</je:container>
V controlu <je:item> se nijak nezabýváme tím, že pole category je typu <Reference>. V atributu field prostě uvedeme jeho jméno a za tečkou pokračujeme polem prvku odkazované kolekce.
Zajímavější je to u controlu <je:aVar>, který používáme k vygenerování odkazu na stránku kategorie a který známe už z /cs/default.aspx. Ten má zde navíc atribut container. Co to znamená? Jak jsme zmínili v minulé kapitole, control <je:avar> potřebuje znát kontext. Potřebuje znát prvek kolekce, jehož identifikátor má dát do URL odkazu. Pokud se nachází v <je:repeater>, pak mu tento svůj kontext předá automaticky. Podobně mu kontext může automaticky předat nejbližší nadřazený <je:container>. To by v tomto případě byl ten, do kterého je zabalená celá stránka – a ten odkazuje na článek, nikoliv na jeho kategorii. A právě to vyřešíme pomocí atributu container=".category".
Více o problematice najdete v článku o Kontejnerování.
Stránka s přehledem článků z kategorie
Zbývá nám již jen vytvořit stránku, na které jsou uvedeny články z dané kategorie. Do souboru /cs/category.aspx umístíme následující kód:
<%@ Page %>
<je:container runat="server" expect="blogPostCategory">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<je:stylelink runat="server" href="/assets/css/main.css" />
<title>Kategorie: <je:item runat="server" field=".title" /></title>
</head>
<body>
<header>
<je:a runat="server" class="logo" href="/cs/">Můj blog</je:a>
<nav>
<je:a runat="server" href="/cs/">Homepage</je:a>
<je:a runat="server" href="/cs/about.aspx">O autorovi</je:a>
</nav>
</header>
<main>
<h1>Kategorie: <je:item runat="server" field=".title" /></h1>
<je:repeater runat="server"
source="blogPost"
restrictField="category">
<item>
<h2>
<je:avar runat="server" href="blogpost.aspx">
<je:item runat="server" field=".title" />
</je:avar>
</h2>
<je:item runat="server" field=".published" tag="time" />
<je:item runat="server"
field=".text"
format="length: 300"
tag="p" />
</item>
</je:repeater>
</main>
</body>
</html>
</je:container>
Stránka je téměř stejná, jako /cs/default.aspx s výpisem všech článků, kterou jsme vyrobili v kapitole Blog za 5 minut. Liší se pouze ve dvou detailech:
- Celá stránka je zabalená v
<je:container>, který zachytává proměnnou kategorie. <je:repeater>má atributrestrictField, který zajistí, že<je:repeater>vypíše jen články, jejichž polecategoryodkazuje na stejnou proměnnou, kterou obsahuje nadřazený kontejner – v našem případě ten, do kterého je zabalená celá stránka.