Michael Mauracher
Michael Mauracher

Reputation: 201

Typo3 - dynamic layout

I would like create a dynamic Typo3 - Fluid layout. The width of the columns should be adjusted automatically. Through the restrictions of Fluid and Typoscript I have problems to formulate the complex condition of the center column. The AND, OR operators are not working.

I hope that somebody can help me.

Typoscript:

variables {
      top < styles.content.get
      top.select.where = colPos=3
      left < styles.content.get
      left.select.where = colPos=1
      center < styles.content.get
      center.select.where = colPos=0
      right < styles.content.get
      right.select.where = colPos=2
      footer < styles.content.get
      footer.select.where = colPos=4
    }

Layout:

<div class="container-fluid">
  TEST: {f:if(condition:'{right} AND {left}', then:'8', else:'{f:if(condition:\'{left} OR {right}\', then: \'9\', else:\'12\')}')}
  <div class="row">
    <div id="top_nav">
      {top -> f:format.raw()}
    </div>
  </div>
  <div class="row">
    <f:if condition="{left}">
      <div id="left" class="col-xs-12 col-md-{f:if(condition:'{right}', then:'2', else:'3')}">
        {left -> f:format.raw()}
      </div>
    </f:if>

    <div id="center" class="col-xs-12 col-md-{f:if(condition:'{right} AND {left}', then:'8', else:'{f:if(condition:\'{left} OR {right}\', then: \'9\', else:\'12\')}')}">
      {center -> f:format.raw()}
    </div>

    <f:if condition="{right}">
      <div id="right" class="col-xs-12 col-md-{f:if(condition:'{left}', then:'2', else:'3') }">
        {right -> f:format.raw()}
      </div>
    </f:if>
  </div>

Upvotes: 0

Views: 531

Answers (2)

undko
undko

Reputation: 937

That‘s just a lot of logic for template. If you decide to do it in an template try to not repeat your conditions, especially in inline notation ({f:if(…)}). I prefer using sections, be it in the same template/partial file or another, over setting variables.

Your code can get as readable as this:

<f:section="main">
    <f:if condition="{right}">
        <f:then>
            <f:if condition="{left}">
                <f:then><f:comment>left and right</f:comment>
                    <f:render section="top" arguments="{top:top}" />
                    <f:render section="left" arguments="{columns:2,left:left}" />
                    <f:render section="center" arguments="{columns:8,center:center}" />
                    <f:render section="right" arguments="{columns:2,right:right}" />
                </f:then>
                <f:else><f:comment>right only</f:comment>
                    <f:render section="top" arguments="{top:top}" />
                    <f:render section="center" arguments="{columns:9,center:center}" />
                    <f:render section="right" arguments="{columns:3,right:right}" />
                </f:else>
            </f:if>
        </f:then>
        <f:else>        
            <f:if condition="{left}">
                <f:then><f:comment>left only</f:comment>
                    <f:render section="top" arguments="{top:top}" />
                    <f:render section="left" arguments="{columns:3,left:left}" />
                    <f:render section="center" arguments="{columns:9,center:center}" />
                </f:then>
                <f:else><f:comment>neither left nor right</f:comment>
                    <f:render section="top" arguments="{top:top}" />
                    <f:render section="center" arguments="{columns:12,center:center}" />
                </f:else>
            </f:if>
        </f:else>
    </f:if>
</f:section>

<f:section name="top">
    <div class="row">
        <div id="top_nav">
            {top -> f:format.raw()}
        </div>
    </div>
</f:section>

<f:section name="left">
    <div id="left" class="col-xs-12 col-md-{columns}">
        {left -> f:format.raw()}
    </div>
</f:section>

<f:section name="right">
    <div id="right" class="col-xs-12 col-md-{columns}">
        {right -> f:format.raw()}
    </div>
</f:section>

<f:section name="center">
    <div id="center" class="col-xs-12 col-md-{columns}">
        {center -> f:format.raw()}
    </div>
</f:section>

As for the condition part, IMO it‘s the maximum a fluid template should be put in. As your logic advances in complexity consider using a data processor. You can test your columns before your view‘s being rendered and assign the result to your template and use fluid layouts for your purpose.

You‘ll need some php skills for data processors. Good starting point to understand them from code ist TYPO3\CMS\Frontend\DataProcessing\CommaSeparatedValueProcessor.

Upvotes: 2

rob-ot
rob-ot

Reputation: 1264

Logical operators will only be available from TYPO3 v8

https://wiki.typo3.org/Fluid#Logical_operators

also, if you like to set a new variable (what you like to do with the class name) you could set your logic outside your html with the VHS variable set viewhelper: https://fluidtypo3.org/viewhelpers/vhs/master/Variable/SetViewHelper.html

an example:

<f:if condition="{right}">
<f:then> 
<v:variable.set name="classCenter" value="2" /> 
</f:then> 
<f:else>
<v:variable.set name="classCenter" value="9" /> 
</f:else>
</f:if>

<div id="center" class="col-xs-12 col-md-{classCenter}" >

You will ofcourse need to install vhs and set the namespace in your fluid template: {namespace v=FluidTYPO3\Vhs\ViewHelpers}

Upvotes: 3

Related Questions