Search the FirstSpirit Knowledge Base
Hallo zusammen,
Ich würde gerne bei der Generierung meiner Navigation (rendertemplates) die ID des Navigationspunkts + Label und einem Boolean "IsMapped" einer Datenquelle hinzufügen.
Meine Seite ist ein "One-Pager" und braucht somit Ankerpunkte.. Ich will mit dem befüllen dieser Datenquelle bezwecken, dass der Redakteur beim Anlegen einer Sektion eine Auswahl von Menüpunkten hat (Label als Preview) und hinter dem Label dann die ID steckt, die wiederum als Ankerpunkt mit dem Menü verknüpft ist. (href)
Mein Problem ist, dass ich es nicht schaffe mit der FirstSpirit-Syntax Datensätze hinzuzufügen... Ist das nur über ein Skript möglich?
Mein Ansatz sieht wie folgt aus:
<CMS_ARRAY_PARAM name="unselectedHTML">
<CMS_ARRAY_ELEMENT index="0..4"><![CDATA[
<a href="#$CMS_VALUE(#nav.label)$">$CMS_VALUE(#nav.label.convert2)$ $CMS_IF(#nav.hasSubFolders)$<em></em>$CMS_END_IF$</a>
$CMS_SET(set_navDBAccess,global.gca("nav_db_access"))$
$CMS_SET(set_navRow,{
"tt_id":#nav.id,
"tt_label": #nav.label,
"tt_isMapped": true
})$
$CMS_SET(void,set_navDBAccess.set(#nav.label,set_navRow))$
]]></CMS_ARRAY_ELEMENT>
</CMS_ARRAY_PARAM>
Habe es mit FS_DataSet und FS_INDEX versucht. Habe ebenfalls das Objekt, was theoretisch erwartet wird, nachzubilden und zu befüllen und dieses Objekt der "add"-Methode bzw. jetzt bei DataSet hier "set"-Methode zu übergeben. Aber kein Erfolg..
Hat jemand eine Idee? Oder gibt es einen viel besseren Ansatz Navigation aufzubauen bei einem One-Page Template mit Ankerpunkten?
Viele Grüße
Peter
Hallo Peter,
Ich habe das so selber noch nicht für "SPA-artiges" benutzt, war erstmal als Hinweis gedacht, dass es diesen Mechanismus gibt. Ob es in Deinem konkreten Fall wirklich passt kann ich nicht sagen.
Die grobe Idee war, Dein initiales Konstrukt und/oder auch die Sichtweise quasi "umzudrehen". Anstatt eine (Inhalts-)Seite in FS zu haben, innerhalb derer man eine Navigationsstruktur hat (bzw. irgendwie eine erzeugt), baut man mehrere Seiten - sorgt dann aber per Dokumentengruppe dafür, dass diese "nachträglich" in einer einzelnen Seite/Datei zusammengefasst werden.
Das Ganze hat allerdings auch ein paar Nachteile, insbesondere kann man Dokumentengruppen im CC nicht (ohne Skripting) anlegen (aber anzeigen). Der Vorteil ist halt, dass Du die ganzen Aspekte bzgl. Hierarchie (Anlegen, Navigation) "geschenkt" bekommst und im CC die "Einzelseiten" pflegen würdest, was oft auch einfacher ist. Wenn das "es ist eine einzige Seite" (=eine HTML-Datei) eher ein rein "technischer" Aspekt ist (wie bei SPAs), sind Dokumentengruppen oft eine sinnvolle Option. Im Template muss man allerdings auch einige Anpassungen machen, insbesondere die Abfrage ob die Seite gerade über die Dokumentengruppe oder "solo" erzeugt wird.
Viele Grüße
Michael
Hallo Peter,
das geht auf diesem Weg nicht - und ich bin mir auch nicht sicher, ob das hier ein sinnvoller Weg wäre. Erstens ist sowieso während der Generierung kein Schreibzugriff möglich (readonly session), außerdem würdest Du ja bei jeder Vorschau-Anforderung neue Datensätze anlegen.
Ich glaube mir ist das Konstrukt / Zielbild noch nicht ganz klar... Du hast eine Navigation, die aber nur innerhalb einer Seite funktionieren soll. Dieser Seite soll der Redakteur Absätze hinzufügen und gleichzeitig einen Eintrag für die seiteninterne Navigation machen? Welche Struktur soll die Navigation haben - ist sie "flach"? Sollen denn mehrere Absätze unterhalb eines Navigationspunktes möglich sein?
Viele Grüße
Michael
Hallo Michael,
Das Klicken eines Navigationspunktes lässt den User zu einem SECTION-Container scrollen (automatisch). Das heißt, dass der href in dem Navigationspunkt kein #nav.ref ist sondern eine ID des SECTION-Containers...
Wie bekomme ich da eine bestimmte Synchronität hin? Also das die SECTION-ID die gleiche ist die in dem Navigationspunkt. Freie Text-Inputfelder sind meiner Meinung nach eine potenzielle Fehlerquelle und bricht bei einem größeren Projekt sehr schnell zu einer Unübersichtlichkeit aus... Deswegen wollte ich die IDs in einer Datenbank persistieren... Nur gefällt mir dieser Ansatz auch nicht wirklich
Viele Grüße
Peter
Hallo Peter,
soll denn zu jedem Absatz ein Navigationspunkt erstellt werden, d.h. entsprechen die SECTIONs den FS-Absätzen? Oder soll es da noch irgendeine Kontrollmöglichkeit geben oder kann das grundsätzlich "automatisch" anhand der vorhandenen Infos passieren?
Generell haben die FS-Absätze eine ID. Im jeweiligen Absatztemplate kannst Du darauf mit
$CMS_VALUE(#global.section.id)$
zugreifen.
Viele Grüße
Michael
Hallo Michael,
Nein, nicht jeder Absatz ist ein Navigationspunkt. Aber die Absätze, die zu einem Navigationspunkt gehören, können auch z.B. über einen Footer-Anker drauf zugegriffen werden.
Beispiel:
Navigation Home hat den href #home
Dann gibt es noch
<SECTION ID="home"> CONTENT </SECTION>
<SECTION ID="aboutUs"> CONTENT </SECTION>
<SECTION ID="contact"> CONTENT </SECTION>
==> Klick auf Navigationspunkt Home ==> Scrollt zu der Stelle wo die Section Home beginnt
----
Generell habe ich über deinen oben genannten Ansatz auch schon nachgedacht. Jedoch weiß die Navigation nichts von dieser FS-Absatz-ID oder? Ich muss ja die ID bei der Ausführung des Rendertemplates schon wissen...
Viele Grüße
Peter
Hallo Peter,
an die FS-Absätze kommst Du auch über eine Iteration heran:
$CMS_FOR(for_section, #global.page.getChildren(class("de.espirit.firstspirit.access.store.pagestore.Section"), true))$
...ID:$CMS_VALUE(for_section.id)$
$CMS_END_FOR$
Das for_section ist dann eine Section aus der API.
Die Frage ist letztlich, woher die Labels für die Navigation kommen (sollen). Und wie man einem Absatz am sinnvollsten sagt, dass er einen Navigationspunkt darstellt. Hier ist es wohl am einfachsten, diese Infos am Absatz selbst zu pflegen, z.B. mit einem Toggle "st_hasNavEntry" und "st_navLabel" (oder Du nimmst für den Nav-Label die Überschrift falls das passt). Oder beide Infos in ein INPUT_LINK auslagern (dann ist der Zugriff ein bisschen anders). Theoretisch könnte man hier die Metadaten für nutzen, die hätten aber den Nachteil nicht sprachabhängig zu sein.
Im Seitentemplate (bzw. Rendertemplate) - Erzeugen der Navigation:
$CMS_FOR(for_section,
#global.page.getChildren(class("de.espirit.firstspirit.access.store.pagestore.Section"), true)
.toList
.filter(section -> section.formData.st_hasNavEntry==true)
)$
<a href ="#section_$CMS_VALUE(for_section.id)$">$CMS_VALUE(for_section.formData.st_navLabel.convert2)$</a>
$CMS_END_FOR$
Und im jeweiligen Absatz (bzw. auch dort ausgelagert in ein Rendertemplate):
<section $CMS_VALUE(if(st_hasNavEntry==true, "id=\"section_"+#global.section.id+"\""))$>
...
</section>
Viele Grüße
Michael
Hallo Michael,
Vielen Dank erstmal für die ausführliche Antwort.
Wenn ich das richtig verstehe, kann ich nun nicht mehr die CMS_FUNCTION Navigation werden? Weil wir diese nicht mehr über die Struktur erstellen? Das hieße, ich müsste diese Funktionalität manuell über eine FOR-Schleife nachbilden? Das heißt auch die Erstellung des Sub-Menus? Dazu bräuchte ich wiederum eine Auswahl bereits bestehender Hauptmenüpunkte, falls es ein Unterpunkt sein sollte...
EDIT: Kann ich dann auf die Struktur verzichten?
Viele Grüße
Peter
Hallo Peter,
zum Verständnis: Geht es hier eher um eine einzelne Seite mit „ein paar“ Einsprungpunkten (in page navigation) oder um eine Art SPA wo die ganze Site in einer Seite „lebt“? Ich war bis jetzt eher von Ersterem ausgegangen.
Viele Grüße
Michael
Hallo Michael,
Sowohl als auch...
Die Einstiegsseite ist eine SPA. Dort findet man u.A. ein Navigationspunkt wie Services und Unterpunkte mit Service1 und Service2 etc. und das alles auf eine Single-Page-Application mit Ankerpunkten(href="#about_us" etc...).
Zusätzlich gibt es aber auch ein Navigationspunkt der heißt Gallery, der wiederum auf eine neue Seite verlinkt ist..
Mein Ansatz wäre jetzt gewesen für eine Sektion:
Anschließend in deiner oben genannten FOR-Schleife diese Form-Data Elemente berücksichtigen..
Evtl. noch unter der eigen-erstellen-Projekteinstellungsseite diese Liste benutzerseitig sortierbar machen und dann diese der FOR-Schleife übergeben..
Für die Navigationspunkte, die auf eine neue Seite verweisen, würden nachwievor über die Struktur erstellt werden... (Bin aber eher unzufrieden mit der Mischung von zwei Erstellungsmethoden für die Navigation...)
Sind alles aber erste spontane Ideen die im Moment durch meinen Kopf fliegen..
Bisheriger Stand:
<CMS_HEADER>
<CMS_FUNCTION name="Navigation" resultname="fr_nav">
<CMS_PARAM name="expansionVisibility" value="all"/>
<CMS_PARAM name="wholePathSelected" value="1" />
<CMS_VALUE_PARAM name="root" value="ss_navRoot"/>
<CMS_ARRAY_PARAM name="innerBeginHTML">
<CMS_ARRAY_ELEMENT index="0..3"><![CDATA[
<ul>
]]></CMS_ARRAY_ELEMENT>
</CMS_ARRAY_PARAM>
<CMS_ARRAY_PARAM name="beginHTML">
<CMS_ARRAY_ELEMENT index="0..4"><![CDATA[
<li class="$CMS_IF(#nav.hasSubFolders)$sub-menu$CMS_END_IF$ sub-menu-$CMS_VALUE(#nav.level)$">
]]></CMS_ARRAY_ELEMENT>
</CMS_ARRAY_PARAM>
<CMS_ARRAY_PARAM name="unselectedHTML">
<CMS_ARRAY_ELEMENT index="0..4"><![CDATA[
$CMS_IF(#nav.comment.isEmpty)$
$CMS_ELSE$
<a href="$CMS_REF(#nav.ref)$">$CMS_VALUE(#nav.label.convert2)$ $CMS_IF(#nav.hasSubFolders)$<em></em>$CMS_END_IF$</a>
$CMS_END_IF$
]]></CMS_ARRAY_ELEMENT>
</CMS_ARRAY_PARAM>
<CMS_ARRAY_PARAM name="selectedHTML">
<CMS_ARRAY_ELEMENT index="0..4"><![CDATA[
$CMS_IF(#nav.comment.isEmpty)$
$CMS_ELSE$
<a href="$CMS_REF(#nav.ref)$" class="active">$CMS_VALUE(#nav.label.convert2)$ $CMS_IF(#nav.hasSubFolders)$<em></em>$CMS_END_IF$</a>
$CMS_END_IF$
]]></CMS_ARRAY_ELEMENT>
</CMS_ARRAY_PARAM>
<CMS_ARRAY_PARAM name="endHTML">
<CMS_ARRAY_ELEMENT index="0..4"><![CDATA[
</li>
]]></CMS_ARRAY_ELEMENT>
</CMS_ARRAY_PARAM>
<CMS_ARRAY_PARAM name="innerEndHTML">
<CMS_ARRAY_ELEMENT index="0..3"><![CDATA[
</ul>
]]></CMS_ARRAY_ELEMENT>
</CMS_ARRAY_PARAM>
</CMS_FUNCTION>
</CMS_HEADER>
$--
This template will create a navigation.
--$
<div class="navbar-collapse navbar-collapse_ collapse">
<ul class="nav navbar-nav sf-menu clearfix">
$CMS_FOR(for_section,
#global.page.getChildren(class("de.espirit.firstspirit.access.store.pagestore.Section"), true)
.toList
.filter(section -> section.formData.st_hasNavEntry==true)
)$
<li class="sub-menu">
<a href ="#section_$CMS_VALUE(for_section.id)$">$CMS_VALUE(for_section.formData.st_navLabel.convert2)$</a>
</li>
$CMS_END_FOR$
$CMS_VALUE(fr_nav)$
</ul>
</div>
Viele Grüße
Peter
Hallo Peter,
für „SPA-artiges“ bieten sich vielleicht „Dokumentengruppen“ an, schau dir das mal im ODFS an. Kurzversion: Damit kann man die Ausgabe mehrerer Seitenreferenzen (bzw. auch kompletter Strukurordner) in EINER Datei bündeln.
Vorteil: Eine „logische“ Seite ist auch in FirstSpirit eine Seite.
Viele Grüße
Michael