Zum Inhalt springen

2 spaltiges Fluid-Template

Erstellt am 31. Dezember 2013 · 24 Antworten · letzte Antwort am 5. Januar 2014 · Seite 1 von 2

Tags: Fluid, ViewHelper, TYPO3 4.x, Frage

WimDim ·

Hallo Zusammen,

ich habe ein 2 spaltiges Layout und hätte gerne eine Darstellung von links nach rechts.
Also: 1 Eintrag Links -> 1 Eintrag Rechts
2 Eintrag Links -> 2 Eintrag Rechts
usw.

Mein Typoscript sieht wie folgt aus:

page.10 = FLUIDTEMPLATE
page.10 {
  partialRootPath = fileadmin/templates/partials/
  layoutRootPath = fileadmin/templates/layouts/

  variables {
    headertext < styles.content.get
    headertext.select.where = colPos = 0
    
    content_left < styles.content.get
    content_left.select.where = colPos = 1
    content_left.renderObj.stdWrap.wrap = <div class="left"> | </div>

    content_right < styles.content.get
    content_right.select.where = colPos = 2
    content_right.renderObj.stdWrap.wrap =  <div class="right"> | </div>
  }
}

Nur gibt das allerdings folgende Ausgabe:

<div class="left"></div>
<div class="left"></div>
<div class="left"></div>
<div class="right"></div>
<div class="right"></div>
<div class="right"></div>

Ich hätte aber gerne:
<div class="left"></div>
<div class="right"></div>
<div class="left"></div>
<div class="right"></div>
<div class="left"></div>
<div class="right"></div>

Kann mir hier jemand weiterhelfen?

Vielen Dank schon mal.

Schweriner ·

In deinem Fall würde ich wohl in Fluid nur ein Typoscript Objekt einbinden. Im Typoscript würde ich dann ein CONTENT Objekt erstellen um die Datensätze zu holen und diese dann mit dem Fluid Viewhelper "cycle" abwechselnd links und rechts ausgeben.

Wenn es wirklich abwechselnd sein soll, dann frage ich mich, warum Du die colPos noch in deine Abfrage mit einbeziehst. Du könntest Alternativ auch mit einem optionSplit jeweils abwechselnde wraps vergeben.

WimDim ·

Hallo Schweriner,
vielen Dank für die Antwort.
Die Variante mit dem CONTENT Objekt hört sich gut an, leider weiss ich nicht genau, wie ich das einsetzen kann, bzw. mit Fluid verbinden kann. Kannst du mir vielleicht einen Tipp geben?

Vielen Dank.

Schweriner ·

Im Fluid Template etwa so:
<f:cObject typoscriptObjectPath="lib.someLibObject" />

Und im Typoscript etwas ála

lib.someLibObject = CONTENT
lib.someLibObject {
table = tt_content
select {
pidInList = this
orderBy = sorting
}
}

Vielleicht musst Du das Select noch anpassen.

WimDim ·

Super, danke.
Ich habe das jetzt so umgesetzt wie Du gesagt hast, und die Inhalte werden mir auch angezeigt. Nun müsste ich allerdings jeweils um die Inhalte immer abwechselnd <div class="left"></div> UND
<div class="right"></div> wrappen. Wie kann ich denn nun die einzelnen Inhalte mit einem wrap versehen?

Schweriner ·

Irgendwie so könnte es funktionieren.

<f:for each="{f:cObject(typoscriptObjectPath: 'lib.someLibObject')}" as="foo" iteration="iter">
<f:if condition="iter.isOdd">
<f:then>
  Links Ausgabe
  {foo}
</f:then>
<f:else>
  Rechte Ausgabe
  {foo}
</f:else>
</f:for>
WimDim ·

Hallo,
nun erhalte ich folgende Fehlermeldung:
#1237900529: The argument "each" was registered with type "array", but is of type "string" in view helper "Tx_Fluid_ViewHelpers_ForViewHelper"

Das fehlende </f:if> am Ende habe ich schon ergänzt. Woran kann das liegen?

Schweriner ·

Tjoa dann liefert das Typoscript wohl fast wie ich es befürchtet habe einen String anstelle eines Arrays zurück. Irgendwie brauchst Du für den For Viewhelper aber ein Array :-x

WimDim ·

Das hört sich ja nicht gut an :-).
Gibt es nicht eine andere Möglichkeit, das von mir gewünschte Ergebnis mittels Content Object zu erreichen?

WimDim ·

Nein, leider auch nicht. Das bleibt bei "right".
Gibt es keine Möglichkeit, hier:

page.10 = FLUIDTEMPLATE
page.10 {
  partialRootPath = fileadmin/templates/partials/
  layoutRootPath = fileadmin/templates/layouts/

  variables {
    headertext < styles.content.get
    headertext.select.where = colPos = 0

    content_left < styles.content.get
    content_left.select.where = colPos = 1
    content_left.renderObj.stdWrap.wrap = <div class="left"> | </div>

    content_right < styles.content.get
    content_right.select.where = colPos = 2
    content_right.renderObj.stdWrap.wrap =  <div class="right"> | </div>
  }

}

eine Codezeile einzubauen, die alle Einträge immer Zeilenweise ausgibt? (Ich weiss, ist der "alte" Aufbau!)

Prinzipiell möchte ich lediglich ein 2-Spaltiges Layout, bei dem sich die rechte Spalte der linken Spalte in der Höhe automatisch anpasst. Wenn es dafür eine Lösung gibt, wäre mir sehr geholfen.

WimDim ·

Hallo Jenses,
über CSS wird das ja schon gesteuert, aber dafür muss ich die Reihenfolge halt immer abwechselnd haben. Ich würde das schon gerne über Typoscript und Templates machen, da nicht jeder (wenn auch nur wenige Leute) Javascript aktiviert hat. Gibt es denn da nicht eine Art "Split" oder so?

typix ·

Hallo zusammen,

ja, der Sprung von TYPO3 4.5 auf TYPO3 6.x ist offenbar selbst für die "alten Hasen" doch nicht ganz so einfach.

Das ist (fast) perfekt:

    page.10 = FLUIDTEMPLATE
    page.10 {
[Es fehlt]
    templateRootPath = fileadmin/templates/template/irgendwas.html
[/]
    partialRootPath = fileadmin/templates/partials/
    layoutRootPath = fileadmin/templates/layouts/
     
    variables {
    content_left < styles.content.get
    content_left.select.where = colPos = 1
     
    content_right < styles.content.get
    content_right.select.where = colPos = 2
    }
    }

Das ist Murks:

    headertext < styles.content.get
    headertext.select.where = colPos = 0

    content_left.renderObj.stdWrap.wrap = <div class="left"> | </div>
     
    content_right.renderObj.stdWrap.wrap = <div class="right"> | </div>
    }
    }

Warum? Ganz einfach. Wie ist der Standardaufbau einer Seite in HTML?

html
header
/header
body
Dein Code
/body
Footer
/Footer
/html

Oder so. Ich schreibe das jetzt nur aus dem Gedächtnis. Also bitte keine Meckerei über Details🙂

In anderen Worten: Hier will jemand Inhalte, die idR über das TS mit page.10.headerdata dem Header einer Seite zugewiesen werden, über die Ausgabe von headertext.select.where = colPos = 0 rendern lassen. Sorry, aber colPos = 0 ist die Spalte "Normal" im Body der Seite. Wie bitte soll TYPO3 Inhalte des Body in den Header schreiben????

2. Fehler:
Im TS bzw. im Setup der Page definiert man idR nur die Subparts, die dann von den Fluid-Templates gerendert werden. Die Idee mit:

 content_left.renderObj.stdWrap.wrap = <div class="left"> | </div>

kann nicht funzen.

CSS-Container werden mit Fluid bitte schön SO in den Templates zugewiesen:

<f:layout name="Default" />

<div class="left">
        <f:format.html parseFuncTSPath="">{content_left}</f:format.html>
</div>

Ob man diese Zuweisung nun im Haupttemplate, im Layout oder den Partials macht, bleibt jedem selbst überlassen.

Viele Grüsse

etux ·

Hallo typix,
Es ist keineswegs alles falsch, was Du sagst. 🙂
Eher hast Du was missverstanden, bzw. verwechselst Du paar Dinger. 😉
Ins Detail gehen, kann ich leider gerade nicht. Außerdem würde eine daraus entstehende Diskussion dem Thread hier nicht unbedingt dienlich. Da gebe ich Dir völlig Recht. 😉

WimDim ·

Hallo Zusammen und vielen Dank für die Informationen.
Ich kriege es leider beim besten Willen nicht hin, dass die Inhalte immer abwechselnd gezeigt werden. Ich möchte links einen kurzen Text und rechts dann eine lange Beschreibung. Beim nächsten Eintrag, soll der 2te kurze Text links erst unterhalb der Höhe des ersten Beschreibungstextes auf der rechten Seite erscheinen.

Also in etwa so:

1. Lorem Ipsum      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 
                    sed diam nonumy eirmod tempor invidunt ut labore et dolore 
                    magna aliquyam erat, sed diam voluptua. At vero eos et accusam 
                    et justo duo dolores et ea rebum. Stet clita kasd gubergren, 
                    no sea takimata sanctus est Lorem ipsum dolor sit amet.

2. Lorem Ipsum      Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 
                    sed diam nonumy eirmod tempor invidunt ut labore et dolore 
                    magna aliquyam erat, sed diam voluptua. At vero eos et accusam 
                    et justo duo dolores et ea rebum. Stet clita kasd gubergren, 

usw. ...

Anbei mal der Code, den ich bisher habe.

page.10 = FLUIDTEMPLATE
page.10 {
  partialRootPath = fileadmin/templates/partials/
  layoutRootPath = fileadmin/templates/layouts/

  variables {
    headertext < styles.content.get
    headertext.select.where = colPos = 1

    content_left < styles.content.get
    content_left.select.where = colPos = 2

    content_right < styles.content.get
    content_right.select.where = colPos = 3
  }

}

page.10.file.stdWrap.cObject = CASE
page.10.file.stdWrap.cObject {
  default = TEXT
  default.value = fileadmin/templates/twoColumn.html

  2 = TEXT
  2.value = fileadmin/templates/twoColumn.html
}

page.includeCSS {
  file1 = fileadmin/templates/css/style.css
}

und das Template:

<f:layout name="main" />
<f:section name="content">
  <div id="headertext"><f:format.html parseFuncTSPath="lib.parseFunc">{headertext}</f:format.html></div>
  <div id="left">
     <f:format.html parseFuncTSPath="lib.parseFunc">{content_left}</f:format.html>
  </div>
  <div id="right">
    <f:format.html parseFuncTSPath="lib.parseFunc">{content_right}</f:format.html>
  </div>
</f:section>

Vielen Dank für eure Mühe :-)

########################################## NACHTRAG ##########################################

Nach langem Ausprobieren, habe ich nun einen Aufbau über MARKER erstellt und auch hier erhalte ich wieder zuerst alle linken Elemente, dann alle rechten Elemente ist hier eine splittung der Content-Elemente vielleicht einfacher?

Anbei mal mein Typoscript:

page.stylesheet = fileadmin/templates/css/style.css

page.typeNum = 0
 
page.10 = TEMPLATE

page.10.template = FILE

page.10.template.file = fileadmin/templates/template.html

page.10.workOnSubpart = DOCUMENT_BODY

page.10.subparts {
     
HEADER = CONTENT
HEADER {
table = tt_content
select.orderBy = sorting
select.languageField = sys_language_uid
select.where = colPos = 1
renderObj < tt_content
}
 
LEFTCONTENT = CONTENT
LEFTCONTENT {
table = tt_content
slide = -1
select.orderBy = sorting
select.languageField = sys_language_uid
select.where = colPos = 2
renderObj < tt_content
renderObj.stdWrap.wrap = <div class="content_left"> | </div>
}
  
RIGHTCONTENT= CONTENT
RIGHTCONTENT {
table = tt_content
slide = -1
select.orderBy = sorting
select.languageField = sys_language_uid
select.where = colPos = 3
renderObj < tt_content
renderObj.stdWrap.wrap = <div class="content_right"> | </div>
}
    MENU = HMENU

    MENU.1 = TMENU
    MENU.1 {
        NO = 1
      wrap = <ul class="mainNav">|</ul>
      expAll = 1
      NO.wrapItemAndSub = <li class="first">|</li>|*|<li>|</li>|*|<li class="last">|</li>
              
      ACT < .NO
      ACT = 1
      ACT.wrapItemAndSub = <li class="active">|</li>
    }
     
    MENU.2 = TMENU
    MENU.2 {
        NO = 1
      wrap = <ul class="submenu">|</ul>
      NO.allWrap = <li class="subfirst">|</li>|*|<li>|</li>|*|<li class="sublast">|</li>
    }
}

Vielen Dank.

show.jpg

etux ·

So lange Du die Backend-Spalten einzeln im Template einbindest, wird das schwierig zu realisieren.
Theoretisch ginge es, die Inhaltselementen aus den zwei Backend-Spalten über TypoScript (oder im Fluid-Template) paarweise zu sortieren und an einer Stelle im Template einzubinden.
Noch einfache wäre es, wenn Du auch im Backend mit nur eine Spalte arbeitest.
Wobei Du dann nicht unbedingt Klassen bräuchtest – wie es auch ohne extra Klassen gehen könnte, siehst Du ja in meinem Beispiel (s. Beitrag vom 03.01.2014, 11:55).