AAC58282E381440B9513489C8A68895D
  • Thomas Pollinger
  • 17.05.2018
  • DE

Navigation mit Rendertags oder doch lieber mit Blockmarkierungen?

Im zweiten Artikel (letzte Woche) aus dieser Serie Erweiterungen bei den Blockmarkierungen - Warum macht das Sinn? wurden bereits einige Ideen, welche die Blockmarkierungen auszubauen, gezeigt.

Jedoch es geht noch mehr, denn wenn man sich weitere Gedanken macht. Kommt man schnell auf den Bereich im CMS, der sehr wichtig ist - die Navigation. Diese wird aktuell mit einer weiteren, anderen Technologie umgesetzt und in die Seiten gerendert - den s.g. Rendertags. Braucht man die dafür wirklich oder geht es auch anders? Das wird dieser Artikel behandeln - wie man mit Blockmarkierungen auch Navigationsstrukturen aufbauen könnte.


Navigation

Was bedeutet Navigation für eine Webseite, welche der primäre Anwendungsfall für eine Web Content Management System (WCMS) wäre:

  • Meta-Navigation
  • Footer-Navigation
  • Haupt-(Main)-Navigation
  • Left- oder Righthand-Navigation
  • Breadcrumb

evtl kann man auch noch weitere Dinge wie z.B.:

  • Backlinks
  • Tabbed-Navigation
  • Dropdown-Navigation

dazuzählen. Aktuell können die Rendertags folgende Funktionalitäten, welche immer wieder innerhalb einer Navigation verwendet werden:

  • Index-Abfragen (First, Current, Last, Root)
  • Selektierte und nicht selektierte Navigationspunkte
  • Foreach-Schleifen
  • If/Else-Bedingungen
  • HasChildren-Abfragen
  • RenderMode

Im letzten Artikel habe ich Beispiele für die folgende Funktionalität aufgezeigt:

  • Rendermodes 2.0
  • If/Else - Bedingung
  • ForEach - Schleife

damit würden noch:

  • Index-Abfragen
  • Selektierte und nicht selektierte Navigationspunkte
  • HasChildren-Abfragen

übrig. Diese könnte man auch über passende neue Blocktypen abbilden.
 

Navigation mit Blockmarkierungen

Wenn man sich nun ganz die aktuelle Funktionalität ansieht, gibt es sogar schon einige Dinge, welche man wiederverwenden könnte:

Breadcrumb

Es gibt eine Funktion im CMS, welche seit dem Navigation-Manager kaum genutzt, jedoch noch vorhanden ist:

<!IoRangeBreadCrumb>
    <%Breadcrumb%>
<!/IoRangeBreadCrumb>

In Kombination mit den Optionen auf den Seiteneigenschaften:

wäre man, mit einem kleinen Umbau im System, direkt in der Lage eine Breadcrumb aufzubauen.

Beispiel

<ul>
    <!IoRangeBreadCrumb><%NavigationBreadcrumb%><!/IoRangeBreadCrumb>
</ul>

alternativ wäre auch denkbar:

<ul>
    <!IoRangeNavigationArea><%NavigationBreadcrumb%><!/IoRangeNavigationArea>
</ul>

das würde dann in der Seite an der Stelle für die Ausgabe der Breadcrumb stehen. Dazu gibt es aber auch noch eine Content-Klasse, wie heute, welche die Ausgabe für das Element <%NavigationBreadcrumb%> definiert. Denn das Element <%NavigationBreadcrumb%> ist ein neues, spezielles Navigationselement, in dem der Verweis zur entsprechenden Content-Klasse für das Rendering der Navigation enthalten ist.

In der Content-Klasse, für die Breadcrumb steht dann z.B. dieser Template-Code:

<li>
<!IoRangeIf>
    <!IoRangeConstraint> <%CurrentIndex%> -ne <%LastIndex%> <!/IoRangeConstraint>
    <!IoRangeThen> <!IoRangeNavigation><a href="<%InfoPageUrl%>"><%HeadlinePage%></a><!/IoRangeNavigation> | <!/IoRangeThen>
    <!IoRangeElse> <b><%HeadlinePage%></b> <!/IoRangeElse>
<!/IoRangeIf>
</li>

<!IoRangeIf>
    <!IoRangeContraint> <%CurrentIndex.HasChildren()%> <!/IoRangeConstraint>
    <!IoRangeThen> <!IoRangeNavigation> <%CurrentIndex.NextLevel()%> <!/IoRangeNavigation> <!/IoRangeThen>
<!IoRangeIf>

damit das ganze nun nicht alles nur grün und gelb ist, habe ich mir erlaubt weitere Farben einzuführen:

<ul>
    <!IoRangeBreadCrumb> <%NavigationBreadcrumb%> <!/IoRangeBreadCrumb>
</ul>
<ul>
    <!IoRangeNavigationArea> <%NavigationBreadcrumb%> <!/IoRangeNavigationArea>
</ul>

und jetzt auch noch das Template für das Rendering der Navigation besser lesbar:

<li>
<!IoRangeIf>
    <!IoRangeConstraint> <%CurrentIndex%> -ne <%LastIndex%> <!/IoRangeConstraint>
    <!IoRangeThen> <!IoRangeNavigation><a href="<%InfoPageUrl%>"><%HeadlinePage%></a><!/IoRangeNavigation> | <!/IoRangeThen>
    <!IoRangeElse> <b><%HeadlinePage%></b> <!/IoRangeElse>
<!/IoRangeIf>
</li>

<!IoRangeIf>
    <!IoRangeConstraint> <%CurrentIndex.HasChildren()%> <!/IoRangeConstraint>
    <!IoRangeThen> <!IoRangeNavigation> <%CurrentIndex.NextLevel()%> <!/IoRangeNavigation> <!/IoRangeThen>
<!IoRangeIf>

Die ebenfalls neue Blockmarkierung <!IoRangeNavigation> ... <!/IoRangeNavigation> funktioniert ähnlich wie eine Liste, jedoch wird sich hier der Navigationsindex zu Hilfe herangezogen. Und ebenfalls immer nur der aktive Navigationspunkt. Dann wird über die Element-Hochreich-Funktion (wie bei der Liste) die Element innerhalb der Blockmarkierung von der aktiven Masterpage übertragen. Ebenfalls die weitere neue Blockmarkierung <!IoRangeConstraint> ... <!/IoRangeConstraint> wäre sehr hilfreich, um komplexe Abfragen zu realisieren. Mein Kollege David hat sich hier als Delivery Server Experte mit eingebracht und die Constraint-Idee entwickelt. Dazu gibt es in einem weiteren Artikel noch mehr Details.

Auch wurden nun, dass ist aber erstmal eine reine Idee, s.g. Inline-Element-Funktionen eingesetzt:

<%CurrentIndex.HasChildren()%>
<%CurrentIndex.NextLevel()%>

um die Elemente noch flexibler zu gestalten. Dazu wird es noch mehr in einem nachfolgenden Artikel geben, um im Detail aufzuzeigen welche weiteren Möglichkeiten damit ergeben.

Hier jetzt nochmals zum Vergleich, der Aufbau mit Rendertags:

<reddot:cms>
    <htmltext><li></htmltext>
    <if>
        <query valuea="Context:CurrentIndex" operator="!=" valueb="Context:LastIndex">
            <htmltext><a href="<%!! Context:CurrentIndex.Page.GetUrl() !!%>"><%!! Context:CurrentIndex.Page.Headline !!%></a> | </htmltext>
        </query>
        <query type="else">
            <htmltext><b><%!! Context:CurrentIndex.Page.Headline !!%></b></htmltext>
        </query>
    </if>
    <htmltext></li></htmltext>
    <if>
        <query valuea="Context:CurrentIndex.HasChildren()" operator="==" valueb="Bool:True">
            <htmltext><navigation:nextlevel></htmltext>
        </query>
    </if>
</reddot:cms>

Man sieht direkt den Unterschied in der Syntax und auch durch die erweiterte visuelle Hervorhebung. Wird die Lesbarkeit direkt massiv verbessert, ebenfalls behält man die Regeln der Blockmarkierungen und Elemente bei. Bei den Rendertags ist es technisch auch lösbar, jedoch meiner Erfahrung nach immer etwas aufwändiger als gedacht.
 

Sitemap

Auch eine Sitemap wäre, mit einem Umbau des bestehenden Sitemap-Elements und der Verwendung der aktuellen Option in den Seiteneigenschaften eine feine Sache:

und wenn man nun sich dazu folgende Syntax vorstellt:

<ul>
    <!IoRangeNavigationArea> <%NavigationSitemap%> <!/IoRangeNavigationArea>
</ul>

Jetzt noch das passende Template für das Rendering der Navigation:

<li>
<!IoRangeNavigation><a href="<%InfoPageUrl%>"><%HeadlinePage%></a><!/IoRangeNavigation>
<!IoRangeIf>
    <!IoRangeConstraint> <%CurrentIndex.HasChildren()%> <!/IoRangeConstraint>
    <!IoRangeThen> <ul> <!IoRangeNavigation> <%CurrentIndex.NextLevel()%> <!/IoRangeNavigation> </ul> <!/IoRangeThen>
<!/IoRangeIf>
</li>

oder statt der Seitenüberschrift, den o.g. Sitemap-Name:

<li>
<!IoRangeNavigation><a href="<%InfoPageUrl%>"><%SitemapNamePage%></a><!/IoRangeNavigation>
<!IoRangeIf>
    <!IoRangeConstraint> <%CurrentIndex.HasChildren()%> <!/IoRangeConstraint>
    <!IoRangeThen> <ul> <!IoRangeNavigation> <%CurrentIndex.NextLevel()%> <!/IoRangeNavigation> </ul> <!/IoRangeThen>
<!/IoRangeIf>
</li>

Wenn man jetzt z.B. beide Varianten haben möchte, jedoch nicht weiß ob der Sitemap-Name befüllt ist, wäre das auch eine denkbare Variante:

<li>
<!IoRangeNavigation><a href="<%InfoPageUrl%>">
<!IoRangeIfExists>
    <%SitemapNamePage%>
    <!IoRangeThen> <%SitemapNamePage%> <!/IoRangeThen>
    <!IoRangeElse> <%HeadlinePage%> <!/IoRangeElse>
<!/IoRangeIfExists>
</a><!/IoRangeNavigation>
<!IoRangeIf>
    <!IoRangeConstraint> <%CurrentIndex.HasChildren()%> <!/IoRangeConstraint>
    <!IoRangeThen> <ul> <!IoRangeNavigation> <%CurrentIndex.NextLevel()%> <!/IoRangeNavigation> </ul> <!/IoRangeThen>
<!/IoRangeIf>
</li>

Man sieht direkt, auch die Kombination der verschiedenen Blocktypen macht durchaus Sinn.
 

Weitere Möglichkeiten für eine Navigation

Es gibt jedoch noch weitere Möglichkeiten wie man eine Navigation mit Blockmarkierungen aufbauen kann. Wichtig dabei sind die Metadaten aus dem Navigationsindex. Dazugehören vorallem die Info ob ein Eintrag "selektiert" oder "nicht selektiert" ist. Dies wird aktuell im Management Server mit einem Mapping und entweder einer oder zwei Content-Klassen je Ebene gelöst. Dies könnte mit Blockmarkierungen z.B. so aussehen:

<ul>
    <!IoRangeNavigationArea> <%NavigationLeftHand%> <!/IoRangeNavigationArea>
</ul>

und dann die entsprechende Content-Klasse für das Rendering der Navigation:

<li>
<!IoRangeIf>
    <!IoRangeConstraint> <%CurrentIndex.IsSelected()%> <!/IoRangeConstraint>
    <!IoRangeThen> <!IoRangeNavigation><a href="<%InfoPageUrl%>"> <b><%HeadlinePage.ToUpper()%></b></a><!/IoRangeNavigation> <!/IoRangeThen>
    <!IoRangeElse> <!IoRangeNavigation><a href="<%InfoPageUrl%>"><%HeadlinePage%></a><!/IoRangeNavigation> <!/IoRangeElse>
<!/IoRangeIf>
<!IoRangeIf>
    <!IoRangeConstraint> <%CurrentIndex.HasChildren()%> <!/IoRangeConstraint>
    <!IoRangeThen> <ul><!IoRangeNavigation> <%CurrentIndex.NextLevel()%> <!/IoRangeNavigation></ul> <!/IoRangeThen>
<!IoRangeIf>
</li>

In diesem Beispiel wird aufgezeigt, dass man auch mit einer Content-Klasse inkl. passender Abfrage eine LeftHand oder andere Navigation aufbauen könnte.


Zwischen-Fazit

Auch im dritten Artikel, in dem es nur um die Navigation geht, sieht man deutlich, dass die Blockmarkierungen sehr viel Potential haben. Vorallem mit weiteren Farben, je nach Kategorie (Schleifen, Bedingungen, Navigation, etc.), kann man eine schnellere Lesbarkeit und ein besseres Verständnis für den Inhalt eines Templates erreichen. Auch die bereits aufgezeigten Element-Inline-Funktionen, wären eine sehr elegante Erweiterung des Elementsystems. Da der Management Server intern auf .NET C# aufsetzt, könnte das auch ein Vorteil für eine solche Erweiterung sein. Doch dazu, wie schon erwähnt, in einem späteren Artikel aus dieser Serie mehr.

Natürlich sollte man ganz genau sich überlegen, ob man z.B. das Mapping wie aktuell oder in dem zuvor genannten eigenen Navigations-Element macht. Was man wie überträgt von den Rendertags zu den Blockmarkierungen und was dann plötzlich überflüssig wird. Doch meiner Meinung nach wäre das eine erstklassige Sache, denn je mehr ich darüber nachdenke und die o.g. Beispiele aufbaue. Desto mehr gefällt mir das erweiterte Blockmarkierungssystem bzw. die Art/Weise wie man damit arbeiten kann.

Jedoch ist noch lange nicht Schluss, es gibt noch weitere Ideen, welche man mit Blockmarkierungen umsetzen könnte. Dazu mehr im nächsten Artikel: Weitere sinnvolle und hilfreiche Blockmarkierungen - gibt es die überhaupt?


Über den Autor:
Thomas Pollinger

... ist Senior Site Reliability Engineer bei der Vodafone GmbH in Düsseldorf. Seit dem Jahr 2007 betreut er zusammen mit seinen Kollegen die OpenText- (vormals RedDot-) Plattform Web Site Management für die deutsche Konzernzentrale.

Er entwickelt Erweiterungen in Form von Plug-Ins und PowerShell Skripten. Seit den Anfängen in 2001 (RedDot CMS 4.0) kennt er sich speziell mit der Arbeitweise und den Funktionen des Management Server aus.