TYPO3 Fluid complex if conditions

dmanners picture dmanners · Nov 1, 2013 · Viewed 41.3k times · Source

I am trying to write the following if condition in fluid but it is not working as I would hope.

Condition As part of a for loop I want to check if the item is the first one or 4th, 8th etc

I would have thought the following would work but it display the code for every iteration.

<f:if condition="{logoIterator.isFirst} || {logoIterator.cycle % 4} == 0">

I have managed to get it working with a nested if but it just feels wrong having the same section of code twice and also having the cycle check use a <f:else> instead of == 0

<f:if condition="{logoIterator.isFirst}">
    <f:then>
        Do Something
    </f:then>
    <f:else>
        <f:if condition="{logoIterator.cycle} % 4">
            <f:else>
                Do Something
            </f:else>
        </f:if>
    </f:else>
</f:if>

Answer

Daniel picture Daniel · Nov 2, 2013

TYPO3 v8

Updated the answer for TYPO3 v8. This is quoted from Claus answer below:

Updating this information with current situation:

On TYPO3v8 and later, the following syntax is supported which fits perfectly with your use case:

<f:if condition="{logoIterator.isFirst}">
    <f:then>First</f:then>
    <f:else if="{logoIterator.cycle % 4}">n4th</f:else>
    <f:else if="{logoIterator.cycle % 8}">n8th</f:else>
    <f:else>Not first, not n4th, not n8th - fallback/normal</f:else>
</f:if>

In addition there is support for syntax like this:

<f:if condition="{logoIterator.isFirst} || {logoIterator.cycle} % 4">
    Is first or n4th
</f:if>

Which can be more appropriate for some cases (in particular when using a condition in inline syntax where you can't expand to tag mode in order to gain access to the f:else with the new if argument).

TYPO3 6.2 LTS and 7 LTS

For more complex if-Conditions (like several or/and combinations) you can add your own ViewHelper in your_extension/Classes/ViewHelpers/. You just have to extend Fluids AbstractConditionViewHelper. The simple if-ViewHelper that shipps with Fluid looks like this:

class IfViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractConditionViewHelper {

    /**
     * renders <f:then> child if $condition is true, otherwise renders <f:else> child.
     *
     * @param boolean $condition View helper condition
     * @return string the rendered string
     * @api
     */
    public function render($condition) {
        if ($condition) {
            return $this->renderThenChild();
        } else {
            return $this->renderElseChild();
        }
    }
}

All you have to do in your own ViewHelper is to add more parameter than $condition, like $or, $and, $not etc. Then you just write your if-Conditions in php and render either the then or else child. For your Example, you can go with something like this:

class ExtendedIfViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractConditionViewHelper {

    /**
     * renders <f:then> child if $condition or $or is true, otherwise renders <f:else> child.
     *
     * @param boolean $condition View helper condition
     * @param boolean $or View helper condition
     * @return string the rendered string
     */
    public function render($condition, $or) {
        if ($condition || $or) {
            return $this->renderThenChild();
        } else {
            return $this->renderElseChild();
        }
    }
}

The File would be in your_extension/Classes/ViewHelpers/ExtendedIfViewHelper.php Then you have to add your namespace in the Fluid-Template like this (which enables all your self-written ViewHelpers from your_extension/Classes/ViewHelpers/ in the template:

{namespace vh=Vendor\YourExtension\ViewHelpers}

and call it in your template like this:

<vh:extendedIf condition="{logoIterator.isFirst}" or="{logoIterator.cycle} % 4">
  <f:then>Do something</f:then>
  <f:else>Do something else</f:else>
</vh:extendedIf>

Edit: updated.