th_biedermann
Occasional Collector

In Forschlaufe weitere CMS_FUNCTION aufrufen

Jump to solution

Hallo zusammen

Ich habe eine Forschlaufe, bei der eine weitere CMS_FUNCTION aufgerufen wird.

Hier versuche ich den CMS_VALUE_PARAM für die CMS_FUNCTION zu setzen:
$CMS_SET(set_recruiterbild, job.Recruiterbild)$

Dann die CMS_FUNCTION aufrufen
$CMS_FOR(recruiter, fr_recruiterData)$
$CMS_SET(item_recruiter, recruiter)$
$CMS_END_FOR$

Das Porblem ist nun, dass ich immer den selben Wert zurückbekomme

 

<CMS_HEADER>
	<CMS_FUNCTION name="contentSelect" resultname="fr_jobData">
	  	<CMS_PARAM  name="schema" value="sfs_inserate_erecruiting" />	  
			<QUERY entityType="SFS_INSERATE_ERECRUITING">
				<AND>			
					<NEQ attribute="Stellentitel" datatype="java.lang.String" value=""/>					
				</AND>
				<ORDERCRITERIA attribute="Stellenid" descending="1" />
			</QUERY>
	</CMS_FUNCTION>

	<CMS_FUNCTION name="contentSelect" resultname="fr_recruiterData">
		<CMS_PARAM  name="schema" value="sfs_cms_db" />
		<CMS_VALUE_PARAM name="recruiterId" value="set_recruiterbild" />
		<QUERY entityType="T_CONTACT">
			<FILTERPARAM parameter="recruiterId" datatype="java.lang.Long" />
			<AND>
				<EQ attribute="fs_id" parameter="recruiterId" />
			</AND>
		</QUERY>
	</CMS_FUNCTION>
</CMS_HEADER>
$CMS_TRIM(level:3)$
$CMS_IF(!fr_jobData.isEmpty() || fr_jobData.size > 0)$
	$CMS_FOR(job, fr_jobData)$

		$CMS_SET(set_recruiterbild, job.Recruiterbild)$
		$CMS_FOR(recruiter, fr_recruiterData)$
			$CMS_SET(item_recruiter, recruiter)$
		$CMS_END_FOR$

 

 

 

 

Danke für einen Tipp

Grüsse. Thomas

0 Kudos
3 Solutions

Accepted Solutions

Hallo Holger

Hat geklappt.

1. Seitenvorlage:

$CMS_SET(set_myRecruiterList,[])$
$CMS_RENDER(
   template: "find_recruiter",
   pa_recruiterID: job.Recruiterbild
 )$

2. Formatvorlage:

<CMS_HEADER>

	<CMS_FUNCTION name="contentSelect" resultname="fr_recruiterData">
		<CMS_PARAM  name="schema" value="sfs_cms_db" />
		<CMS_VALUE_PARAM name="recruiterId" value="pa_recruiterID" />
		<QUERY entityType="T_CONTACT">
			<FILTERPARAM parameter="recruiterId" datatype="java.lang.Long" />
			<AND>
				<EQ attribute="fs_id" parameter="recruiterId" />
			</AND>
		</QUERY>
	</CMS_FUNCTION>

</CMS_HEADER>

$CMS_FOR(recruiter, fr_recruiterData)$
	$CMS_SET(set_myRecruiterList[0], recruiter.FIRSTNAME)$
	$CMS_SET(set_myRecruiterList[1], recruiter.LASTNAME)$
	$CMS_SET(set_myRecruiterList[2], recruiter.PHONE)$
	$CMS_SET(set_myRecruiterList[3], recruiter.EMAIL)$
$CMS_END_FOR$

3. Ausgabe:

"contact":{
  "languageIsoCode":"de",
  "firstName":"$CMS_VALUE(set_myRecruiterList[0])$",
  "lastName":"$CMS_VALUE(set_myRecruiterList[1])$",
  "phone":"$CMS_VALUE(set_myRecruiterList[2])$",
  "email":"$CMS_VALUE(set_myRecruiterList[3])$"
},

 

Jetzt habe ich die korrekten Recruiter bei der jeweiligen Stelle.

DANKE für die pompte Hilfe 🙂

Grüsse. Thomas

View solution in original post

0 Kudos

Hallo Michael

Sorry, ich stehe wohl auf dem Schlauch. Ich bekomme immer noch eine Werte raus. Was mache ich hier noch falsch. Du hattest geschrieben, dass ich die Map auch den RendererTemplate übergeben soll. Habe ich das so korrekt gemacht?

Renderer:

$CMS_RENDER(
template: "get_recruiter",
pa_recruiterID: job.Recruiterbild,
pa_recruiterMap: {:}
)$

Renderertemplate wie du beschreiben hast:

$CMS_FOR(recruiter, fr_recruiterData)$
$CMS_SET(void, pa_recruiterMap.putAll({
"firstname":recruiter.FIRSTNAME,
"lastname":recruiter.LASTNAME,
"phone":recruiter.PHONE,
"email":recruiter.EMAIL
})
)$

Ausgabe habe ich über verschiedene Arten versucht:

$CMS_VALUE(pa_recruiterMap.get("firstname")$

$CMS_VALUE(pa_recruiterMap.firstname)$

DANKE und Grüsse

Thomas

View solution in original post

0 Kudos

Hallo Michael

Ich habe das Problem doch noch gefunden 🙂 Die Map habe ich ausserhalb des Renderers gesetzt. Nun kann ich auf die Map zugreifen und die Werte ausgeben.

Ich muss sagen, dass ist natürlich die viel bessere Lösung. Und so ist alles klar wenn z.b. auf "firstname" zugreifen kann und nicht auf einen Array-Wert z.B. "0" 🙂

$CMS_SET(pa_recruiterMap, {:})$

$CMS_RENDER(
template: "get_recruiter",
pa_recruiterID: job.Recruiterbild,
)$

$CMS_VALUE(pa_recruiterMap.get("firstname"))$

Besten DANK und Grüsse

Thomas

View solution in original post

0 Kudos
10 Replies
hoebbel
Crownpeak employee

Guten Morgen Thomas,

das hat etwas mit der Auswertungsreihenfolge zu tun. Die contentselect Funktion wird ausgewertet, wobei die im Context zur Verfügung stehenden Informationen (also z.B. die Werte aus Eingabekomponenten oder einem im Kontext "höheren" Template benutzt werden. Das Ergebnis bleibt dann erhalten, so dass nicht bei jedem Aufruf der Funktion eine neue Datenbankabfrage gemacht werden muss.

Das ist normalerweise von Vorteil, bei Deinem Anwendungsfall führt das aber zu dem nicht gewünschten Ergebnis.

Lösung: Nutze ein Formattemplate, um die contentSelect Funktion auszuführen. Dazu definierst Du einfach im Formattemplate einen <CMS_HEADER> und schreibst da die contentSelect Funktion rein. 

Nächste Stolperfalle ist dann aber, dass der Kontext der Formatvorlage nur solange lebt, wie die Formatvorlage ausgeführt wird. Beim nächsten Schleifendurchlauf ist alles weg, was in der Formatvorlage gemacht wird, solange es nicht ausgegeben wurde (oder zu einem höheren Kontext gehört).

Lösung dafür ist dann, entweder alle Ausgaben, die sich auf die innere contentSelect Funktion beziehen, in der Formatvorlage zu machen (das ist am einfachsten, aber leider nicht immer fachlich ausreichend) oder die Informationen in den höheren Kontext zu "retten".
Letzteres geht auf zwei Arten:
Entweder im höheren Kontext eine Variable definieren (Liste, Map), die im niedrigeren Kontext modifiziert wird oder in niedrigeren Kontext eine Variable definieren, die zum höheren Kontext gehört.

Beispiele:
Absatzvorlage: $CMS_SET(set_myTempList,[])$$CMS_RENDER(template:"<UID der Formatvorlage>",myVar:<zu übergebener Wert>)$
Formatvorlage: $CMS_SET(set_myTempList[0],<zu rettender Inhalt>)$
Absatzvorlage: set_myTempList[0] hat nun den zu rettenden Wert

Wie man Variablen in einen anderen Kontext schreibt, findest Du in diesem Bereich der Doku:
https://docs.e-spirit.com/odfs/vorlagenentwick/variablen/kontexte/index.html
Da ist auch erklärt, welche Kontexte es gibt und wie die heißen (der Kontext des Absatz heißt z.B. "section", der der Seite "PAGE" {Groß und Kleinschreibung muss beachtet werden})

Ich hoffe, dass hilft weiter.
Viele Grüße
Holger

0 Kudos

Hallo Holger

Hat geklappt.

1. Seitenvorlage:

$CMS_SET(set_myRecruiterList,[])$
$CMS_RENDER(
   template: "find_recruiter",
   pa_recruiterID: job.Recruiterbild
 )$

2. Formatvorlage:

<CMS_HEADER>

	<CMS_FUNCTION name="contentSelect" resultname="fr_recruiterData">
		<CMS_PARAM  name="schema" value="sfs_cms_db" />
		<CMS_VALUE_PARAM name="recruiterId" value="pa_recruiterID" />
		<QUERY entityType="T_CONTACT">
			<FILTERPARAM parameter="recruiterId" datatype="java.lang.Long" />
			<AND>
				<EQ attribute="fs_id" parameter="recruiterId" />
			</AND>
		</QUERY>
	</CMS_FUNCTION>

</CMS_HEADER>

$CMS_FOR(recruiter, fr_recruiterData)$
	$CMS_SET(set_myRecruiterList[0], recruiter.FIRSTNAME)$
	$CMS_SET(set_myRecruiterList[1], recruiter.LASTNAME)$
	$CMS_SET(set_myRecruiterList[2], recruiter.PHONE)$
	$CMS_SET(set_myRecruiterList[3], recruiter.EMAIL)$
$CMS_END_FOR$

3. Ausgabe:

"contact":{
  "languageIsoCode":"de",
  "firstName":"$CMS_VALUE(set_myRecruiterList[0])$",
  "lastName":"$CMS_VALUE(set_myRecruiterList[1])$",
  "phone":"$CMS_VALUE(set_myRecruiterList[2])$",
  "email":"$CMS_VALUE(set_myRecruiterList[3])$"
},

 

Jetzt habe ich die korrekten Recruiter bei der jeweiligen Stelle.

DANKE für die pompte Hilfe 🙂

Grüsse. Thomas

0 Kudos

Hallo Thomas,

ein Hinweis noch: Es ist best practice, in Rendertemplates NIEMALS einfach Variablen aus dem aufrufenden Kontext zu nutzen (in deinem Fall set_myRecruiterList).

Das hat weniger „technische“ Gründe aber aus (eigener leidvoller…) Erfahrung ist hier das Risiko groß, dass diese „versteckte“ Abhängigkeit später - insbesondere wenn so ein Rendertemplate im Laufe der Zeit wächst - vergessen wird. Das führt dann zu schwer zu findenden Fehlern…

Meine Empfehlung wäre darum, die Variable dem Rendertemplate auch als Parameter zu übergeben - und im Rendertemplate selbst natürlich auch alle dort verwendeten Parameter zu dokumentieren.

Außerdem würde ich noch empfehlen in deinem Fall keine Liste sondern eine Map zu nutzen mit den entsprechenden keys. Eine leere Map erzeugst du mit {:}

Viele Grüße 

Michael

0 Kudos

Hallo Michael

Danke für dein Feedback.

Kannst du mir hierzu noch einbischen helfen?

Ich übergebe dem Renderertemplate den Parameter "pa_recruiterID". Dokumentiren muss ich noch machen 🙂

Meine Empfehlung wäre darum, die Variable dem Rendertemplate auch als Parameter zu übergeben - und im Rendertemplate selbst natürlich auch alle dort verwendeten Parameter zu dokumentieren.

Das verstehe ich nicht ganz was ich genau machen soll.

Außerdem würde ich noch empfehlen in deinem Fall keine Liste sondern eine Map zu nutzen mit den entsprechenden keys. Eine leere Map erzeugst du mit {:}

Danke für Deine Hilfe

Grüsse. Thomas

0 Kudos

Ich habe mich mal hinter deine Empfehlung gemacht.

Übergabe RendererTemplate:

 

$CMS_RENDER(
template: "get_recruiter",
pa_recruiterID: job.Recruiterbild,
pa_recruiterMap: {:}
)$
$CMS_END_IF$

 

 

Renderertemplate:

 

$CMS_FOR(recruiter, fr_recruiterData)$
	$CMS_SET(pa_recruiterMap, {
		"firstname":recruiter.FIRSTNAME,
		"lastname":recruiter.LASTNAME,
		"phone":recruiter.PHONE,
		"email":recruiter.EMAIL
		})$
$CMS_END_FOR$

 

 

Ausgabe:

Leider ist die Ausgabe immer leer

 

$CMS_VALUE(pa_recruiterMap.firstname)$

 

 

 

0 Kudos

Hallo Thomas,

die Idee ist hier nicht, die Variable selbst neu zuzuweisen - das kann so nicht funktionieren, weil die Variable selbst im höheren Kontext "lebt". Mit deinem Code wird quasi eine weitere Variable mit demselben Namen im (tieferen) Rendertemplate-Kontext erzeugt, die die aus dem höheren dann "überdeckt". Theoretisch gibt es zwar schon einen Weg, eine Variable aus einem höheren Kontext neu zuzuweisen, der ist aber dann richtig "fies" (aka: BösesVoodoo) und der Anfang vom Chaos - darum macht man sowas halt nicht bzw. nur im allerallergrößten Notfall 😉

Die Idee war, den Inhalt der übergebenen Variablen zu ändern. 

Mit diesem Code im Rendertemplate sollte es gehen: 

$CMS_FOR(recruiter, fr_recruiterData)$
	$CMS_SET(void, pa_recruiterMap.putAll({
		"firstname":recruiter.FIRSTNAME,
		"lastname":recruiter.LASTNAME,
		"phone":recruiter.PHONE,
		"email":recruiter.EMAIL
		})
	)$
$CMS_END_FOR$

 

Das mit dem "void" ist lediglich eine "Konvention" - könnte genausogut huiBuh heißen - um anzuzeigen, dass es an dieser Stelle nicht um die Variable an sich geht, sondern "eigentlich" um den Methodenaufruf, da es um "einfach nur eine Methode aufzurufen keine extra Syntax gibt.

 

0 Kudos

Hallo Michael

Sorry, ich stehe wohl auf dem Schlauch. Ich bekomme immer noch eine Werte raus. Was mache ich hier noch falsch. Du hattest geschrieben, dass ich die Map auch den RendererTemplate übergeben soll. Habe ich das so korrekt gemacht?

Renderer:

$CMS_RENDER(
template: "get_recruiter",
pa_recruiterID: job.Recruiterbild,
pa_recruiterMap: {:}
)$

Renderertemplate wie du beschreiben hast:

$CMS_FOR(recruiter, fr_recruiterData)$
$CMS_SET(void, pa_recruiterMap.putAll({
"firstname":recruiter.FIRSTNAME,
"lastname":recruiter.LASTNAME,
"phone":recruiter.PHONE,
"email":recruiter.EMAIL
})
)$

Ausgabe habe ich über verschiedene Arten versucht:

$CMS_VALUE(pa_recruiterMap.get("firstname")$

$CMS_VALUE(pa_recruiterMap.firstname)$

DANKE und Grüsse

Thomas

0 Kudos

Hallo Michael

Ich habe das Problem doch noch gefunden 🙂 Die Map habe ich ausserhalb des Renderers gesetzt. Nun kann ich auf die Map zugreifen und die Werte ausgeben.

Ich muss sagen, dass ist natürlich die viel bessere Lösung. Und so ist alles klar wenn z.b. auf "firstname" zugreifen kann und nicht auf einen Array-Wert z.B. "0" 🙂

$CMS_SET(pa_recruiterMap, {:})$

$CMS_RENDER(
template: "get_recruiter",
pa_recruiterID: job.Recruiterbild,
)$

$CMS_VALUE(pa_recruiterMap.get("firstname"))$

Besten DANK und Grüsse

Thomas

0 Kudos

Hallo Thomas,

naja, jetzt hast du zwar eine Map aber dadurch dass du die nicht übergibst eigentlich wieder dasselbe "Problem" der zu starken Abhängigkeit.

Das Problem war, dass du einfach direkt eine leere Map als Parameter übergeben hast - diese Map gibt es ja dadurch nicht als Variable im "äußeren" Template.

Das heißt: Besser im äußeren Template die leere Map als Variable definieren, diese Variable dann übergeben:

 

$CMS_SET(set_recruiterMap, {:})$
$CMS_RENDER(
  template: "get_recruiter",
  pa_recruiterID: job.Recruiterbild,
  pa_recruiterMap: set_recruiterMap
)$
$CMS_VALUE(set_recruiterMap.get("firstname"))$

 

Das mag fast gleich aussehen, hat aber den Vorteil dass innerhalb des Rendertemplates keine Abhängigkeit zum Namen der Variablen im äußeren besteht, sondern es in Form der Parameternamen eine "klar definierte Schnittstelle" gibt.

Anstatt set_recruiterMap.get("firstname") kannst du übrigens auch die Kurzversion set_recruiterMap.firstname benutzen um auf den Wert zuzugreifen.

 

0 Kudos