Handbuch · 12

Rezepte

Hauptmenü mit aktivem Punkt

Snippet navigation:

<nav class="hauptmenue">
  <a href="/" {% if page.path == "/" %}aria-current="page"{% endif %}>Start</a>
  {% for p in nav() %}
    <a href="{{ p.path }}" {% if p.path == page.path %}aria-current="page"{% endif %}>{{ p.title }}</a>
  {% endfor %}
</nav>

Die Reihenfolge entspricht dem Seitenbaum, Entwürfe erscheinen nicht. Im CSS: .hauptmenue [aria-current] { font-weight: 700; }.

Untermenü einer Rubrik

{% for p in children() %}
  <a href="{{ p.path }}">{{ p.title }}</a>
{% endfor %}

Team-Seite aus einer Collection

Collection team mit name, rolle, foto (Bild), text (Markdown), dazu eine Komponente person:

{# Snippet "person" #}
<figure class="person">
  {{ image(foto, "(min-width: 800px) 25vw, 50vw") }}
  <figcaption><strong>{{ name }}</strong><br>{{ rolle }}</figcaption>
  {% slot %}{% endslot %}
</figure>
<div class="team">
  {% for p in data("team") %}
    {% component "person" name=p.name rolle=p.rolle foto=p.foto %}{{ p.text|markdown }}{% endcomponent %}
  {% empty %}
    <p>Das Team stellt sich bald vor.</p>
  {% endfor %}
</div>

Produkte aus einem Shop

REST-Quelle produkte: URL https://shop.example.com/api/products?category={kat}&limit=12, Header Authorization: Bearer {env.SHOP_TOKEN}, Listen-Pfad data.items, Cache 600.

<form>
  <select name="kat" onchange="this.form.submit()">
    <option value="">Alle</option>
    <option value="schuhe" {% if route.query.kat == "schuhe" %}selected{% endif %}>Schuhe</option>
  </select>
</form>
{% for p in data("produkte", "kat", route.query.kat) %}
  <article>
    <img src="{{ p.image_url }}" alt="{{ p.name }}" loading="lazy">
    <h3>{{ p.name }}</h3>
    <p>{{ p.price|floatformat:2 }} €</p>
  </article>
{% endfor %}

Jede Kategorie ist ein eigener Cache-Eintrag – sowohl beim REST-Abruf als auch im Seiten-Cache.

Nur kommende Termine

Mit today und einem Datumsvergleich verschwinden vergangene Einträge von selbst – ohne sie zu löschen:

{% for e in data("events", "datum__gte", today, "sort", "datum") %}
  <h3>{{ e.titel }}</h3>
  <p>{{ e.datum|slice:"8:10" }}.{{ e.datum|slice:"5:7" }}.{{ e.datum|slice:"0:4" }}</p>
{% empty %}
  <p>Aktuell sind keine Termine geplant.</p>
{% endfor %}

Ein Archiv zeigt dieselbe Collection mit "datum__lt", today, "sort", "-datum".

Blätternde Liste

Rechnen ist direkt in Ausdrücken möglich (seite - 1, (seite - 1) * 10); |integer macht aus dem Query-Parameter eine Zahl.

{% with seite=route.query.seite|default:"1"|integer %}
  {% for post in data("blog", "sort", "-datum", "limit", 10, "offset", (seite - 1) * 10) %}
    …
  {% endfor %}
  {% if seite > 1 %}<a href="?seite={{ seite - 1 }}">Neuer</a>{% endif %}
  <a href="?seite={{ seite + 1 }}">Älter</a>
{% endwith %}

Seitenbaukasten aus Blöcken

Am bequemsten geht das mit dem eingebauten Seitenbaukasten aus Bausteinen und {% blocks page.blocks %} (siehe 7.6). Ohne Schema klappt es auch mit einer Collection: Collection bloecke mit seite (Text), typ (Auswahl: text, bild, zitat), inhalt (Markdown), bild (Bild). Für jeden Typ ein Snippet block/text, block/bild, block/zitat, die ihre Parameter verwenden. Auf der Seite:

{% for b in data("bloecke", "seite", page.slug) %}
  {% component "block/"|add:b.typ inhalt=b.inhalt|markdown bild=b.bild %}{% endcomponent %}
{% endfor %}

JSON für JavaScript bereitstellen

<script>
  const termine = {{ data("termine", "sort", "datum")|json }};
</script>

Mehrsprachigkeit

Alles Wichtige steht unter Mehrsprachige Websites: Sprache am Seitenbaum setzen (vererbt sich), Fassungen verknüpfen, hreflang und Sitemap kommen automatisch, den Sprachumschalter baust du mit translations(), das Menü je Sprache mit children(lang_root().id).

Kontaktformulare

IllusionCMS verarbeitet keine Formulare selbst. Verwende einen Formular-Dienst oder eine eigene API als action-Ziel und binde dessen Skript als JS-Datei ein.