jan
I'm new here

Zugriff auf den letzten Wert in for-Schleife

Jump to solution

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 😉

0 Kudos
1 Solution

Accepted Solutions
feddersen
Community Manager

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

View solution in original post

0 Kudos
4 Replies
Peter_Jodeleit
Crownpeak employee

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

Peter
feddersen
Community Manager

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

0 Kudos

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.0Smiley Happy

0 Kudos
feddersen
Community Manager

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$

0 Kudos