Search the FirstSpirit Knowledge Base
ich habe in einem Seitentemplate ein contentselect und möchte darin in der for-Schleife den aktuellen Wert mit dem aus vorangegangenen Durchlauf vergleichen:
<CMS_HEADER>
<CMS_FUNCTION name="contentSelect" resultname="cs_mitteilungen_einstellungsdatum">
<CMS_PARAM name="schema" value="wmlbl" />
<QUERY entityType="mitteilungen">
<ORDER>
<ORDERCRITERIA attribute="einstellung" descending="1" />
</ORDER>
</QUERY>
</CMS_FUNCTION>
</CMS_HEADER>
Die Tabelle "mitteilungen" enthält im fraglichen Feld "einstellung" ein Datum. Mein Ziel ist es, eine Liste der eingestellten Mitteilungen zu erzeugen, in der jedes Datum (mich interessiert dabei nur Monat und Jahr) nur einmal vorkommt - in der HTML-Seite soll daraus eine select-box für das Jahr und den Monat erzeugt werden. In normalem sql könnte man das Problem mit "select distinct" oder "group by" lösen, das kann aber der or-Mapper nicht, daher war ich auf die Lösung mit dem Wertvergleich gekommen.
Zunächst dachte ich, ich könnte mit wert[#for.index] und wert[#for.index-1] auf die Felder zugreifen, das funktionierte aber nicht und ich habe es mit der CMS_SET Lösung versucht.
$CMS_FOR(einstellungsdatum,cs_mitteilungen_einstellungsdatum)$
$CMS_SET(datum_neu)$$CMS_VALUE(einstellungsdatum.einstellung.format("yyyyMM").toString.trim(), default:"")$$CMS_END_SET$
$CMS_IF(!datum_neu.toString.equals(datum_alt.toString))$
Ausgabe
$CMS_END_IF$ $CMS_SET(datum_alt)$$CMS_VALUE(einstellungsdatum.einstellung.format("yyyyMM").toString.trim(),default:"")$$CMS_END_SET$
$CMS_END_FOR$
Das Problem an der Sache ist, dass der aktuelle Wert und der letzte Wert nach dem ersten Durchlauf immer gleich ist und daher die IF-Bedingung nie wieder zutrifft.
Da ich hier ja nichts dynamisch verändern will, sollte das Caching des contentselects in meinen Augen keine Rolle spielen.
Trotzdem müsste doch ein Unterschied zwischen datum_alt (gesetzt am Ende eines Schleifendurchlaufs und datum_neu (gesetzt am Anfang eines Schleifendurchlaufs) bestehen.
Hat jemand ein Erklärung dafür oder sitzt das Problem in meinem Fall mal wieder vor dem Computer 😉
Hallo Herr Oltmanns,
die contentSelect-Funktion liefert eine List zurück, die einige Methoden bereitstellt, die Ihnen weiterhelfen solllten. Siehe http://www.e-spirit.com/odfs42/de/vorlagenentwicklung/vorlagensyntax/datentypen/listen/listen.html
Insbesondere die Methoden filter(Lambda) und distict(Lambda).
Hier ein kleines Beispiel, dass sie für ihren Anwendungsfall noch anpassen müssen.
Gegeben ist eine Liste von Immobilien (kann auch das Ergebnis einen contentSelects sein).
Es sollen alle PLZ ausgegeben werden, zu denen es eine Immobilie gibt (ohne doppelte). Die PLZ werden dazu noch sortiert.
Manuell eine Liste erstellen
==========
$CMS_SET(immos, [
{"Name":"A", "Adresse":{"Ort":"Dortmund", "PLZ":44400, "Strasse":"Amsterdamer Platz", "Nr":"32"}, "Preis":177.000, "qmWohn":190},
{"Name":"B", "Adresse":{"Ort":"Dortmund", "PLZ":44400, "Strasse":"Amsterdamer Weg", "Nr":"64"}, "Preis":180.000, "qmWohn":195},
{"Name":"C", "Adresse":{"Ort":"Dortmund", "PLZ":41877, "Strasse":"Alleestr.", "Nr":"114"}, "Preis":150.000, "qmWohn":150},
{"Name":"D", "Adresse":{"Ort":"Dortmund", "PLZ":41877, "Strasse":"Buchenweg", "Nr":"11"}, "Preis":115.000, "qmWohn":100},
{"Name":"E", "Adresse":{"Ort":"Bochum", "PLZ":42345, "Strasse":"Kleiner Weg", "Nr":"2b"}, "Preis":555.000, "qmWohn":320},
{"Name":"F", "Adresse":{"Ort":"Bochum", "PLZ":42345, "Strasse":"Hohe Straße", "Nr":"6"}, "Preis":55.000, "qmWohn":64},
{"Name":"G", "Adresse":{"Ort":"Bochum", "PLZ":42345, "Strasse":"Tiefer Weg", "Nr":"21"}, "Preis":38.000, "qmWohn":37}
])$
$CMS_FOR(_immo, immos.sort(x -> x.Adresse.PLZ).distinct(x -> x.Adresse.PLZ))$
* $CMS_VALUE(_immo.Adresse.PLZ)$<br />
$CMS_END_FOR$
liefert:
* 41877
* 42345
* 44400
Das wäre die "elegante" Variante. Die Variante mit der CMS_FOR funktioniert auch, sie müssen nur folgende Zeile umschreiben.
$CMS_SET(datum_alt)$$CMS_VALUE(einstellungsdatum.einstellung.format("yyyyMM").toString.trim(),default:"")$$CMS_END_SET$
Wenn Sie ein umschließendes CMS_SET verwenden, erfolgt die Zuweisung nicht direkt. Alles innerhalb des CMS_SET wird als Vorlagenfragment betrachtet, dass erst bei der Ausgabe ausgewertet wird. Sie möchten ja den Wert direkt zuweisen, was sie wie folgt erreichen:
$CMS_SET(datum_alt,einstellungsdatum.einstellung.format("yyyyMM").toString.trim())$
Viele Grüße
Christoph Feddersen
In einem kleinem Testfall funktioniert das bei mir tadellos:
$CMS_FOR(i, [1,1,2,2,2,3,3,4])$
$CMS_IF(last != i)$
-$CMS_VALUE(i)$-
$CMS_END_IF$
$CMS_SET(last, i)$
$CMS_END_FOR$
Liefert -1- -2- -3- -4-
Eventuell hilft auch dieser Link bei der Lösungunsfindung javascript:;
Und dann gibt es noch die Funktion "distinct", die eventuell weiterhelfen kann (allerdings gibt es die glaube ich erst seit 4.2R2):
$CMS_VALUE([1,1,2,2,2,3].distinct(x -> x))$ $-- liefert [1, 2, 3] --$
In deinem Fall also so etwas (from brain to keyboard):
$CMS_FOR(i, liste.distinct(x -> x.einstellung.format("yyyyMM"))$ ...
Noch ein paar Anmerkungen:
1) In deinem Pseudo-Code fehlt das setzen von "datum_alt"
2) Das setzen von "datum_neu" sollte so erfolgen: $CMS_SET(datum_neu, einstellungsdatum.einstellung.format("yyyyMM"))$
3) Der Vergleich sollte so erfolgen $CMS_IF(datum_neu != datum_alt)$
Hoffe das hilft weiter
Hallo Herr Oltmanns,
die contentSelect-Funktion liefert eine List zurück, die einige Methoden bereitstellt, die Ihnen weiterhelfen solllten. Siehe http://www.e-spirit.com/odfs42/de/vorlagenentwicklung/vorlagensyntax/datentypen/listen/listen.html
Insbesondere die Methoden filter(Lambda) und distict(Lambda).
Hier ein kleines Beispiel, dass sie für ihren Anwendungsfall noch anpassen müssen.
Gegeben ist eine Liste von Immobilien (kann auch das Ergebnis einen contentSelects sein).
Es sollen alle PLZ ausgegeben werden, zu denen es eine Immobilie gibt (ohne doppelte). Die PLZ werden dazu noch sortiert.
Manuell eine Liste erstellen
==========
$CMS_SET(immos, [
{"Name":"A", "Adresse":{"Ort":"Dortmund", "PLZ":44400, "Strasse":"Amsterdamer Platz", "Nr":"32"}, "Preis":177.000, "qmWohn":190},
{"Name":"B", "Adresse":{"Ort":"Dortmund", "PLZ":44400, "Strasse":"Amsterdamer Weg", "Nr":"64"}, "Preis":180.000, "qmWohn":195},
{"Name":"C", "Adresse":{"Ort":"Dortmund", "PLZ":41877, "Strasse":"Alleestr.", "Nr":"114"}, "Preis":150.000, "qmWohn":150},
{"Name":"D", "Adresse":{"Ort":"Dortmund", "PLZ":41877, "Strasse":"Buchenweg", "Nr":"11"}, "Preis":115.000, "qmWohn":100},
{"Name":"E", "Adresse":{"Ort":"Bochum", "PLZ":42345, "Strasse":"Kleiner Weg", "Nr":"2b"}, "Preis":555.000, "qmWohn":320},
{"Name":"F", "Adresse":{"Ort":"Bochum", "PLZ":42345, "Strasse":"Hohe Straße", "Nr":"6"}, "Preis":55.000, "qmWohn":64},
{"Name":"G", "Adresse":{"Ort":"Bochum", "PLZ":42345, "Strasse":"Tiefer Weg", "Nr":"21"}, "Preis":38.000, "qmWohn":37}
])$
$CMS_FOR(_immo, immos.sort(x -> x.Adresse.PLZ).distinct(x -> x.Adresse.PLZ))$
* $CMS_VALUE(_immo.Adresse.PLZ)$<br />
$CMS_END_FOR$
liefert:
* 41877
* 42345
* 44400
Das wäre die "elegante" Variante. Die Variante mit der CMS_FOR funktioniert auch, sie müssen nur folgende Zeile umschreiben.
$CMS_SET(datum_alt)$$CMS_VALUE(einstellungsdatum.einstellung.format("yyyyMM").toString.trim(),default:"")$$CMS_END_SET$
Wenn Sie ein umschließendes CMS_SET verwenden, erfolgt die Zuweisung nicht direkt. Alles innerhalb des CMS_SET wird als Vorlagenfragment betrachtet, dass erst bei der Ausgabe ausgewertet wird. Sie möchten ja den Wert direkt zuweisen, was sie wie folgt erreichen:
$CMS_SET(datum_alt,einstellungsdatum.einstellung.format("yyyyMM").toString.trim())$
Viele Grüße
Christoph Feddersen
Der verkürzte Set-Befehl liefert das richtige Ergebnis ! Die Sort-Anweisungen klappen auf 4.0 gar nicht, auf 4.2 funktioniert alles, wie vorhergesagt - wir sind leider noch auf 4.0
In 4.0 war die Syntax für Lamba-Ausdrücke noch etwas anders. Sie sollten ja auf ihrem Server eine 4.0 Dokumentation haben, in der Sie das noch mal nachlesen können, aber es sollte so gewesen sein:
LISTE.sort(lambda(p:p.person.Vorname))
Die Variante mit #for.index -1 klappt übrigens auch:
$CMS_FOR(einstellungsdatum, cs_mitteilungen_einstellungsdatum)$
$CMS_IF(#for.index == 0 || (einstellungsdatum.einstellung.format("yyyyMM") != cs_mitteilungen_einstellungsdatum[#for.index - 1].einstellung.format("yyyyMM")))$
$CMS_VALUE(einstellungsdatum.einstellung.format("yyyyMM"))$
$CMS_END_IF$
$CMS_END_FOR$
Hello!
Ich habe ein ähnliches Problem und frage mal hier:
Ich habe auch Datensätze, die ein Datum enthalten. und ich möchte in einer Auswahlbox nur die Jahre haben. Allerdings nicht in der Ausgabe, sondern in der Auswahl im Template.
Ich habe eine Query und eine Combobox und bis auf eine Kleinigkeit tut es das schon.
Das Query macht aktuell nur die Sortierung:
<QUERY entityType="press_article">
<ORDERCRITERIA attribute="date" descending="1"/>
</QUERY>
Die ComboBox wählt nur das Datum aus und formatiert es:
<CMS_INPUT_COMBOBOX name="st_filter_year" hFill="yes" singleLine="no" useLanguages="no">
<CMS_INCLUDE_OPTIONS type="database">
<LABELS>
<LABEL lang="*">#item.date.format("yyyy")</LABEL>
</LABELS>
<QUERY name="tt_press_article_years"/>
<TABLE>tt_press_article</TABLE>
</CMS_INCLUDE_OPTIONS>
<LANGINFOS>
<LANGINFO lang="*" label="Year"/>
</LANGINFOS>
</CMS_INPUT_COMBOBOX>
Was mir fehlt ist ein Distinct im Query oder der ComboBox.
In der Doku bin ich leider nicht fündig geworden. Gibt es hier eine Möglichkeit an mein Ziel zu kommen?
Cheers
Connz