TYPO3 / Fluid

Fluid template rendering engine - Standalone version
GNU Lesser General Public License v3.0
150 stars 93 forks source link

Missing Functionality in Fluid - Collection #862

Open benjaminkott opened 4 months ago

benjaminkott commented 4 months ago

Arrays

Strings

Parent Rendering

I want to be able to render parts of an overwritten template.

<f:parent>

Conditions

First / Last

<f:first value="{0: '1', 1: '2', 2: '3'}"  />
<!-- 1 -->

<f:last value="{0: '1', 1: '2', 2: '3'}"   />
<!-- 3 -->

Min / Max / Random

<f:min value="{0: '1', 1: '2', 2: '3'}" />
<!-- 1 -->

<f:max value="{0: '1', 1: '2', 2: '3'}" />
 <!-- 3 -->

<f:random value="{0: '1', 1: '2', 2: '3'}" />
<!-- 1|2|3 -->

Round

<f:round value="15.341" precision="2" method="ceil" />
<!-- 15.35 -->

Alternative: Dedicated ViewHelpers for each.

Replace #863

Replace a string, with another one.

<f:replace value="HELLO###SPACE###FRIENDS" pattern="###SPACE###" replacement=" " />
<!-- HELLO FRIENDS -->
sandoba commented 4 months ago

Definitely would love to see the remaining functionality of Twig in Fluid. Especially something like would be helpful, when only minor changes of e.g. a section are required. Or perhaps with a change of :

` ...

... </f:render>`

So changes could be made within the scope of the rendered partial or section.

But if it is meant for a template then this would be more akin to an include? E.g.

` ...

... </f:include>`

Could of course also be called <f:render template="ExampleTemplate" ....

s2b commented 4 months ago

Thank you for your feedback! I just want to leave a few comments here. I think, once we've accomplished some of the quick wins (ViewHelpers), we can close this issue and open separate ones for the bigger feature requests.

Arrays

  • reverse loop

This should already be possible:

<f:for each="{myArray}" as="item" reverse="1">
  • map

Just want to leave that here, since it's buried in a review:

I don't think a clean solution like this is possible without syntax changes. Something like this could be possible though:

{csv -> f:split(separator: ',') -> f:map(callback: 'f:trim')}

Strings

  • substring rendering

Do you mean with numbers, like substr($string, 1, 5)?

Parent Rendering

I want to be able to render parts of an overwritten template.

<f:parent>

Conditions

  • strict comparisons
  • contains/includes

Probably a bit more tough to implement, but valid.

Round

Alternative: Dedicated ViewHelpers for each.

I think that 3 ViewHelpers make more sense here to avoid the string constants.

Replace

Replace a string, with another one.

<f:replace value="HELLO###SPACE###FRIENDS" pattern="###SPACE###" replacement=" " />
<!-- HELLO FRIENDS -->

Can we use search and replace instead (like str_replace does)? I find them easier to understand, also search isn't a regular expression here.

It would also be nice to provide one array with key-value pairs (which str_replace() unfortunately doesn't allow). Maybe support these variants:

<f:replace value="HELLO###SPACE###FRIENDS" search="###SPACE###" replace=" " />
<f:replace value="HELLO###SPACE###FRIENDS" search="{0: '###SPACE###'}" replace="{0: ' '}" />
<f:replace value="HELLO###SPACE###FRIENDS" replace="{'###SPACE###': ' '}" />
benjaminkott commented 4 months ago

@s2b Maybe this could be used as a starting point for a parent view helper https://github.com/benjaminkott/bootstrap_package/commit/82a837b78457554dd4d99b6c063975df86789b5b The main problem is that the context is missing when rendering the current template. So guessing/config is needed.

Do you mean with numbers, like substr($string, 1, 5)? Yes, @NeoBlack is a big fan of that.

mkroener commented 3 months ago

Currently, there are contexts such as BackendPreviews or fluid templates in content blocks where preparing data is challenging, and no view helpers are available for a straightforward approach. I've seen solutions where developers crafted a workaround by looping with and self-rendering sections.

Being able to repeat a snippet multiple times would be a valuable initial capability.

<f:repeat times="{slotCount}">
    <div class="item-slot"></div>
</f:repeat>

Its easy to do quick and dirty way:

namespace Your\Extension\ViewHelpers;

use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;

class RepeatViewHelper extends AbstractViewHelper {

    public function initializeArguments() {
        $this->registerArgument('times', 'int', 'How many times to repeat the content', true);
    }

    public function render() {
        $times = $this->arguments['times'];
        $output = '';
        for ($i = 0; $i < $times; $i++) {
            $output .= $this->renderChildren();
        }
        return $output;
    }
}

But it would be great to have as a standard viewhelper