How can I define an array of numbers and output each number in a for loop?
I tried it like this:
<f:alias map="{numbers: [1,2,3,4,5,6]}">
<f:for each="{numbers}" as="number">
<p>{number}</p>
</f:for>
</f:alias>
Result:
The argument "map" was registered with type "array", but is of type "string" in view helper "TYPO3\CMS\Fluid\ViewHelpers\AliasViewHelper"
And like this:
<f:alias map="{v:iterator.explode(content: '1,2,3,4,5,6')}">
<f:for each="{content}" as="zahl">
<p>{zahl}</p>
</f:for>
</f:alias>
Result: No output.
<f:for each="{0:1, 1:2, 2:3, 3:4, 4:5, 5:6, 6:7}" as="foo">{foo}</f:for>
The ideal solution IF and only IF:
You use VHS.
You want numbers starting from 0 or 1 going to a max; or numbers calculated using those two starting indices (TYPO3 8.0+ supports math expressions in Fluid natively, earlier versions require VHS for this).
You want to loop the numbers, not consume them as an array.
Which seems to be exactly your use case...
Then, and only then, is the following the ideal solution in terms of both performance and minimising complexity:
<v:iterator.loop count="6" iteration="iteration">
{iteration.index} starts at zero, {iteration.cycle} starts at one.
</v:iterator.loop>
Don't forget the following either:
{f:render(section: 'OtherSection', arguments: {iteration: iteration})
-> v:iterator.loop(count: 6, iteration: 'iteration')}
Which is the most efficient way of rendering a section X number of times
with only the iteration variable being different. Sections or partials are the most efficient way to represent this exact type of code and the
inline syntax is the most efficient when parsing.
try this:
<f:alias map="{numbers: {1,2,3,4,5,6}}">
<f:for each="{numbers}" as="number">
<p>{number}</p>
</f:for>
</f:alias>
I was able to solve it with this code:
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"
xmlns:v="http://typo3.org/ns/FluidTYPO3/Vhs/ViewHelpers"
v:schemaLocation="https://fluidtypo3.org/schemas/vhs-master.xsd">
<f:for each="{v:iterator.explode(content: '1,2,3,4,5,6')}" as="number">
<p>{number}</p>
</f:for>
Output:
1
2
3
4
5
6
Make sure that you have installed the extension VHS: Fluid ViewHelpers (extension key = vhs).
Make sure to include the extension in the partial.
Write this at the top:
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"
xmlns:v="http://typo3.org/ns/FluidTYPO3/Vhs/ViewHelpers"
v:schemaLocation="https://fluidtypo3.org/schemas/vhs-master.xsd">
I am using Typo3 v6.2.25
Related
I wonder how to do some bit-wise math in a Fluid template. Like a bit-wise AND:
<f:if condition="{var & 2}"> ... </f:if>
But the {var & 2} expression isn't evaluated and remains as a string.
I couldn't find a viewhelper so far. I guess I have to write one?
I want to stop my circle after output first element.
<f:for each="{errors}" as="error">
<f:switch expression="{error.code}">
<f:comment>The given subject was not a valid email address</f:comment>
<f:case value="1221559976">
<f:translate extensionName="helper" key="validator.emailaddress.notvalid" />
</f:case>
...
</f:switch>
BREAK????
</f:for>
Is it possible with fluid? Regards, Anton
You don't even need to iterate the collection, what for? Instead you can just fetch first element like: {errors.0}
Additionally if you want to fetch i.e. first 3 elements, you can prepare $limitedErrors (or smth) in your PHP controller and then assign it into the view.
It will be still more comfortable than manipulating within the template engine.
You can make you for each loop with additional argument iteration=""
add below code
<f:for each="{errors}" as="error" iteration="errorIterator">
and add condition
<f:if condition="{errorIterator.index} = 0">
or
<f:if condition="{errorIterator.isFirst}">
May you can use vhs viewhelper
<v:switch value="{variable}">
<v:case case="someValue" break="TRUE">
<!-- do whatever, if {variable} == 'someValue' -->
</v:case>
<v:case case="default">
<!-- the case "default" is a reserved keyword which acts as the default case. -->
</v:case>
</v:switch>
break > boolean
In the typo3 template I'm using the following line to get the last 5 added items from the backend and this works.
<f:cObject typoscriptObjectPath="lib.lastaddeditmes" />
Only the number of item I want to have it flexible and set in the fluid template. So for example like below where the qty is set to three, is this possible?
<f:cObject typoscriptObjectPath="lib.lastaddeditmes(3)" />
You can't do that in the view, instead you can make a copy of lib.lastaddeditmes in TypoScript and then use it in other place like:
lib.lastaddeditmesOnlyThree < lib.lastaddeditmes
lib.lastaddeditmesOnlyThree.someSetting.items = 3
and in view:
<f:cObject typoscriptObjectPath="lib.lastaddeditmesOnlyThree" />
Remember that TypoScript is just a configuration syntax (not programming language) so it shouldn't give you any huge performance drop.
I am using the extension fluidpages and want to switch the layout by the typeNum.
is it possible to change the f:layout by by an condition?
This wont work:
<f:layout name="{f:if(condition: '{typeNum} == 666', then: 'PageAjax', else: 'Page')}"/>
Suggested approach:
<f:layout name="Page/{typeNum}"/>
Required files:
Resources/Private/Layouts/Page/0.html
Resources/Private/Layouts/Page/666.html
Please note: this only works if the {typeNum} variable is guaranteed to exist - if it does not, you will face a "template file not found" error with an empty filename. To avoid this, you can use the VHS extension's v:var.convert ViewHelper to ensure a proper value:
<f:layout name="Page/{typeNum -> v:var.convert(type: 'integer')}"/>
I got the same problem recently, and found the solution after a few researchings.
The problem is, you can not use nested fluid like <f:if>, <f:cObject> or others in <f:layout>. Otherwise, you will get a fatal error in the cache file, saying call to a member function getViewHelper() on a non-object. And when you look at the cache file, you will find it's because $self is not defined.
Therefore, my solution is, searching public function getLayoutName( in \TYPO3\CMS\Fluid\Core\Compiler\TemplateCompiler, and adding \$self = \$this; before \$currentVariableContainer = \$renderingContext->getTemplateVariableContainer();, just like generateCodeForSection()
I have now added the Condition in the Layout template. I get the typeNum from typoscript.
<f:if condition="{f:cObject(typoscriptObjectPath:'plugin.nc_template.settings.pageLayout')} == 'Default'">
<p>Default Template</p>
</f:if>
<f:if condition="{f:cObject(typoscriptObjectPath:'plugin.nc_template.settings.pageLayout')} == 'Ajax'">
<p>Ajax Template</p>
</f:if>
I found an example on the fedext Page, but could not get this to run:
https://fedext.net/blog/archive.html?tx_news_pi1[news]=55&tx_news_pi1[%40widget_0][currentPage]=8&cHash=f9c3165598a28d2aa98fd30ef115bb75
CanĀ“t you use an if-statement instead?
IMHO this is easier to read - and if you need to add more arguments which depends on typeNum, it would stay readable.
<f:if condition="{typeNum} == 666">
<f:then>
<f:layout name="PageAjax">
</f:then>
<f:else>
<f:layout name="Page">
</f:else>
</f:if>
I have a fluid template, from where I call an often used snippet (called "partial"):
Template:
<f:render partial="fbLikeBox" arguments="{settings}"/>
Partial fbLikeBox.html:
<div id="fb-root"></div><script src="http://connect.facebook.net/xxxxxxxx"></script>
<fb:like href="{settings.baseURL}/details/?guide_uid={audioguide.uid}">
</fb:like>
As you can see, I need both values from the {settings} and the {audioguide} array passed to the partial. How can I achieve that?
Starting with TYPO3 4.6, you could just use
<f:render partial="fbLikeBox" arguments="{_all}" />
The {_all} will simple make sure all variables currently available in your template, are available in the partial.
you can use an array, like:
<f:render partial="fbLikeBox" arguments="{settings : settings, audioguide:audioguide}"/>
They're key : value pairs where the value defines the accessible name in your partial