1

I need to run a fluid loop with chosen number of times, This number of stars is an Integer and not an array, integer from 1 - 5. {Records.numberStars} type INT.

<f:for each="{record.data.stars}" as="stars" iteration="StarsIterator">
    <f:if condition="{stars} < {StarsIterator}">
        <f:render partial="Icon" "/>
    </f:if>
</f:for>

Is there any way to make a loop limited to an integer variable ? Fluid template TYPO3 v12.4

2 Answers 2

2

f:for expects each to be an array, not an integer. So it's not possible to use that if I get you right and {record.data.stars} is an integer and not an array.

There is no beautiful solution out of the box for your problem. But here are some possible solutions:

Use the PHP controller or a DataProcessor to deliver an array

$stars = [
    0 => 1,
    1 => 1,
    2 => 1,
    3 => 1
];
<f:for each="{record.data.stars}" as="stars">
    <f:render partial="Icon" "/>
</f:for>

But if you get the integer value right from a database record, that might not work or you need another custom DataProcessor.

Use f:switch ViewHelper

This solution is rather ugly.

<f:switch expression="{record.data.stars}">
    <f:case value="5">
        <f:render partial="Icon" "/>
        <f:render partial="Icon" "/>
        <f:render partial="Icon" "/>
        <f:render partial="Icon" "/>
        <f:render partial="Icon" "/>
    </f:case>
    <f:case value="4">
        <f:render partial="Icon" "/>
        <f:render partial="Icon" "/>
        <f:render partial="Icon" "/>
        <f:render partial="Icon" "/>
    </f:case>
    <f:case value="3">
        <f:render partial="Icon" "/>
        <f:render partial="Icon" "/>
        <f:render partial="Icon" "/>
    </f:case>
    <f:case value="2">
        <f:render partial="Icon" "/>
        <f:render partial="Icon" "/>
    </f:case>
    <f:case value="1">
        <f:render partial="Icon" "/>
    </f:case>
</f:switch>

Use v:iterator.loop from EXT:vhs

The TYPO3 extension vhs provides a lot of additional ViewHelpers. But it also adds a dependency to your project and makes you dependent on updates by the author of the extension.

But v:iterator.loop does exactly what you want:

<v:iterator.loop count="{record.data.stars}" iteration="star">
    <f:render partial="Icon" "/>
</v:iterator.loop>

Develop a custom ViewHelper

Of course it's also possible to extract the functionality of v:iterator.loop and put it in your own custom ViewHelper.

Sign up to request clarification or add additional context in comments.

Comments

2

As Peter Kraume already mentioned, there's no clean solution to this yet so a custom ViewHelper is the way to go. Here's one I'm using in TYPO3 12 - 13.

You can use it exactly like the for-each ViewHelper

class ForViewHelper extends AbstractViewHelper
{


    /**
     * @var bool
     */
    protected $escapeOutput = false;


    public function initializeArguments()
    {
        parent::initializeArguments();
        $this->registerArgument('start', 'int', 'Start index', true);
        $this->registerArgument('end', 'int', 'End index', true);
        $this->registerArgument('iteration', 'string', 'Iteration data', true);
    }

    /**
     * @param array $arguments
     * @param \Closure $renderChildrenClosure
     * @param RenderingContextInterface $renderingContext
     * @return string
     * @throws ViewHelper\Exception
     */
    public function render()
    {
        $templateVariableContainer = $this->renderingContext->getVariableProvider();
        if (!isset($arguments['start']) || !isset($arguments['end'])) {
            return '';
        }
        $start = (int) $arguments['start'];
        $end = (int) $arguments['end'];

        if (isset($arguments['iteration'])) {
            $iterationData = [
                'index' => 0,
                'cycle' => 1,
                'total' => $end - $start
            ];
        }

        $output = '';

        for ($i = $start; $i < $end; $i++) {
            if (isset($arguments['iteration'])) {
                $iterationData['isFirst'] = $iterationData['cycle'] === 1;
                $iterationData['isLast'] = $iterationData['cycle'] === $iterationData['total'];
                $iterationData['isEven'] = $iterationData['cycle'] % 2 === 0;
                $iterationData['isOdd'] = !$iterationData['isEven'];
                $templateVariableContainer->add($arguments['iteration'], $iterationData);
                $iterationData['index']++;
                $iterationData['cycle']++;
            }
            $output .= $this->renderChildren();;
        }
        return $output;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.