Search the FirstSpirit Knowledge Base
Hallo zusammen,
wir haben bei einem unserer Kunden ein Render-Template, welches aus dem übergebenen "item" eine bestimmte Property auslesen soll.
Das funktioniert soweit auch gut, sofern es sich bei dem item um ein DataProvider Objekt handelt.
Allerdings haben wir hier auch noch verschachtelte Catalogs und in diesem Fall erhalte ich kein Objekt vom Typ DataProvider an die Hand, sondern ein IdentifiableCatalogCardItem.
Ich habe zu diesem Typ bisher nichts in den Dokus gefunden und frage mich nun, wie ich diese korrekt behandeln muss um an deren FormData heranzukommen.
Kann mir einer von Euch da weiterhelfen?
(Ein Link auf die entsprechende Doku wäre schon super)
EDIT:
Duh. Ich bin ein Depp. Das IdentifiableCatalogCardItem _ist_ bereits das FormData!
Jetzt bräuchte ich nur noch einen Weg um von diesem wieder an die CatalogCard zu kommen - wenn das überhaupt geht...
Hallo STrojette,
Du kommst von der Catalog card ja mittels getItem() zu dem CatalogCardItem. Leider "kennt" meines Wissens nach das CatalogCardItem seine Card nicht.
Wenn ich es richtig verstehe, übergebt ihr bereits das Item an das Rendertemplate. Wenn ihr statt dessen die Card übergeben würdet und euch erst im Rendertemplate das Item holt, entsteht das geschilderte Problem gar nicht erst.
Als sauberen Lösungsansatz würde ich dafür einfach die Card übergeben und dann im Rendertemplate das Item daraus holen. Das hat natürlich den Nachteil, dass man alle aufrufenden Stellen anpassen muss. Sofern die CMS_RENDER Aufrufe das Rendertemplate als String direkt aufrufen, findet man die über den Referenzgraphen (STRG-U). Wenn der Aufruf allerdings durch Nutzung einer Variable ausgeführt wird, kennt FirstSpirit diese Information nicht....
Ein wenig frage ich mich, warum ihr denn die Card im Rendertemplate benötigt. Evtl. gibt es ja auch für den Anwendungsfall eine andere Lösung?
Viele Grüße
Holger
Hallo Holger,
genau da liegt das Problem!
Wir haben das Render-Template auf allen unseren Absatzvorlagen eingebunden.
In dieses geben wir einfach immer das #this.
Wenn man eine solche Absatzvorlage nun direkt in den Page-Content einhängt, dann ist #this vom Typ SectionTemplate und alles ist fein.
Liegt die Absatzvorlage aber in einem CATALOG, so ist #this plötzlich nur noch ein IdentifiableCatalogCardItem - und nicht wie erhofft ein CatalogCard.
Wir können also hier meines Wissens nach nichts anderes reingeben.
Das scheint einfach von FirstSpirit automatisch zu passieren. 😞
Hallo STrojette,
funktioniert es, wenn ihr im CATALOG Fall einfach #card übergebt, anstatt #this.
Also eine Abfrage in der Art von:
$CMS_IF(#this.class == class("de.espirit.firstspirit.store.access.pagestore.SectionImpl"))$
<#this>
$CMS_ELSE$
<#card>
$CMS_END_IF$
#card.item müsste dann wieder das Formdata liefern. Mit einem passenden Schalter (weiterer Parameter) kann man dann im Rendertemplate die korrekte Umformung nutzen, ohne die Abfrage dort erneut aufrufen zu müssen.
Viele Grüße
Holger
Hallo Holger,
diese Fallunterscheidung müsste ich dann aber in jeder Absatzvorlage _vor_ dem Aufruf des eigentlichen RenderTemplates machen, das wäre unschön.
Oder kann ich ein Render-Template innerhalb eines Render-Templates aufrufen?
Also sowas wie: $CMS_RENDER(template:"myRenderTemplate", item: render(template: "item_or_card", item1: #this, item2: #card) )$
Falls das geht, was ist wenn #card gar nicht existiert?
Fliegt mir dass direkt bei der Verwendung von #card um die Ohren, oder ist das einfach "null"?
Hallo STrojette,
der Aufruf eines RenderTemplates in einem RenderTemplate ist kein Problem, wenn das im Quelltext des RenderTemplates gemacht wird. ACHTUNG: Den Kontext beachten - das äußere Rendertemplate kann nicht auf Werte zurückgreifen, die im inneren gesetzt wurden.
Trick dazu: Im äußeren Kontext eine Liste definieren und die im inneren Kontext erweitern. Das Objekt steht dann modifiziert im äußeren Kontext zur Verfügung.
Das hier könnte gehen:
$CMS_SET(set_this,[])$
$CMS_RENDER(template:"item_or_card")$
$CMS_RENDER(template:"myRenderTemplate", item:set_this[0])$
Der "Trick" ist, dass im Rendertemplate der "äußere" Kontext zur Verfügung steht. Dort gibt es also #this und gegebenenfalls #card. Dort kannst Du dann einfach
$CMS_IF(#this.class == class("de.espirit.firstspirit.store.access.pagestore.SectionImpl"))$
$CMS_SET(set_this[0],#this)$
$CMS_ELSE$
$CMS_SET(set_this[0],#card)$
$CMS_END_IF$
nutzen.
Es müsste sogar umgedreht funktionieren. Also ganz normal das bisherige Rendertemplate aufrufen, in diesem die Liste definieren und dann das Rendertemplate zur Fallunterscheidung aufrufen. Oder einfach gar nichts übergeben und im Rendertemplate direkt den Kontext prüfen.
WICHTIG: Das funktioniert nur, weil ein Formattemplate #this nicht in seinen Kontext setzt! Umgedreht bedeutet dies natürlich auch, dass Du auf diese Art immer das Element prüfst, welches zuletzt #this in den Kontext gesetzt hat. Das kann man hier ausnutzen, an anderer Stelle kann man da aber auch schnell unerwartete Effekte bekommen 😉
Bitte gründlich prüfen, ich habe es nicht ausprobiert und kann weder Tippfehler noch die Möglichkeit, dass ich irgendetwas nicht bedacht habe, ausschließen...
Viele Grüße
Holger
Ah! Interessant.
$CMS_SET(set_this,[])$
$CMS_RENDER(template:"item_or_card")$
$CMS_RENDER(template:"myRenderTemplate", item:set_this[0])$
Muss ich beim "item_or_card" Template die set_this Liste nicht als Parameter mit reingeben damit die verändert werden kann?
Nein - das RenderTemplate hat Zugriff auf den darumliegenden Kontext, so wie ein Absatz die Variablen der Seite zur Verfügung hat.
Im renderTemplate wird dann das Objekt aus dem umliegenden Kontext modifiziert, so dass dort der modifizierte Wert genutzt werden kann.
Deshalb würde es auch funktionieren, in dem bisherigen RenderTemplate einfach #this aus dem Kontext zu prüfen und dann auf #card zuzugreifen - jedenfalls solange, wie das Rendertemplate ausgeführt wird, während der darumliegende Absatz noch den Kontext zur Verfügung stellt (und das ist der Fall, wenn in dem Absatz CMS_RENDER ausgerufen wird)
Hallo,
kleine Ergänzung zum Thema „Muss ich das als Parameter übergeben um es ändern zu können?“:
Technisch ist das nicht unbedingt notwendig (da man wie Holger schrieb Zugriff auf den umliegenden Kontext hat).
ABER: Ich würde dennoch dringend empfehlen, das so zu machen. Allein schon damit im Rendertemplate wirklich klar ist, was man benutzt. Best practice ist es, in Rendertemplates niemals „einfach Variablen aus äußeren Kontexten zu nutzen“. Es funktioniert zwar, verschleiert aber diese Abhängigkeit und erzeugt eine unnötig starke Abhängigkeit.
Später hat man (oder ein anderer Entwickler) das dann nicht mehr auf dem Schirm was dann bei späteren Anpassungen (eigene leidvolle Erfahrung!) zu sehr schwer zu findenden Fehlern führen kann.
Viele Grüße
Michael