Split detail view in seperate content areas - typo3

How can I split the detail view in seperate content areas?
I configured 2 content areas as backend layouts:
backend_layout {
colCount = 1
rowCount = 2
rows {
1 {
columns {
1 {
name = News-Head
colPos = 0
}
}
}
2 {
columns {
1 {
name = News without Head
colPos = 22
}
}
}
}
}
and 1 News layout for the single view with head only:
tx_news.templateLayouts {
20 = Detail (Head only)
}
after that I inserted the 2 plugins in his associated content areas and select the news layout 20 on a single plugin.
Now I inserted a switch inside the Fluid template detail.html
<f:if condition="{settings.templateLayout} == 20">
<f:then>
<h1>
<f:if condition="{newsItem.alternativeTitle}">
<f:then>
<n:titleTag>
<f:format.htmlentitiesDecode>{newsItem.alternativeTitle}</f:format.htmlentitiesDecode>
</n:titleTag>
</f:then>
<f:else>
<n:titleTag>
<f:format.htmlentitiesDecode>{newsItem.title}</f:format.htmlentitiesDecode>
</n:titleTag>
</f:else>
</f:if>
</h1>
</f:then>
<f:else>
<div class="news news-single">
<div class="article" itemscope="itemscope" itemtype="http://schema.org/Article">
<div class="news-col">
<n:renderMedia news="{newsItem}" imgClass="img-responsive" videoClass="video-wrapper" audioClass="audio-wrapper">
<f:render partial="Detail/MediaContainer" arguments="{media: newsItem.media, settings:settings}" />
</n:renderMedia>
</div>
<div class="news-col">
<f:format.html>{newsItem.bodytext}</f:format.html>
</div>
</div>
</div>
</f:else>
</f:if>
But only the output of else branch works. Why?
Thanks in advance for help.

It was my fault! I totally forgot to pass-through my page variable content_news_single from my main fluid template to my partial.
TS setting:
page.10 = FLUIDTEMPLATE
page.10 {
# ....
variables{
content_main < styles.content.get
content_news_single < styles.content.get
content_news_single.select.where = colPos = 22
}
}
And here I forgot the definition to pass-through the variable content_news_single
<div class="page">
<f:render partial="header" arguments="{content_border:content_border}" />
<f:render partial="body" arguments="{content_main:content_main,content_news_single:content_news_single}" />
<f:render partial="footer" />
</div>
Also I never inserted {newsItem.title}
<f:if condition="{settings.templateLayout} == 20">
<f:then>
<n:format.nothing>
<n:excludeDisplayedNews newsItem="{newsItem}" />
<f:if condition="{newsItem.alternativeTitle}">
<f:then>
<n:titleTag>
<f:format.htmlentitiesDecode>{newsItem.alternativeTitle}</f:format.htmlentitiesDecode>
</n:titleTag>
</f:then>
<f:else>
<n:titleTag>
<f:format.htmlentitiesDecode>{newsItem.title}</f:format.htmlentitiesDecode>
</n:titleTag>
</f:else>
</f:if>
<f:render partial="Detail/Opengraph" arguments="{newsItem: newsItem, settings:settings}" />
</n:format.nothing>
<h1>
{newsItem.title}
</h1>
</f:then>
<f:else>
<div class="news news-single">
<div class="article" itemscope="itemscope" itemtype="http://schema.org/Article">
<div class="news-col">
<n:renderMedia news="{newsItem}" imgClass="img-responsive" videoClass="video-wrapper" audioClass="audio-wrapper">
<f:render partial="Detail/MediaContainer" arguments="{media: newsItem.media, settings:settings}" />
</n:renderMedia>
</div>
<div class="news-col">
<f:format.html>{newsItem.bodytext}</f:format.html>
</div>
</div>
</div>
</f:else>
</f:if>

Related

EXT:Form - Get layout field from content object data

I'm trying to get the layout field of the content object data inside an ext:form content element, to add a css class if a specific layout has been chosen. But nether the content object data is added to the fluid template (typo3/sysext/form/Classes/Controller/FormFrontendController.php:73) nor the frame container from fluid_styled_content is rendered for this element.
My layout field is configured like this:
TCEFORM.tt_content {
layout {
types.form_formframework {
addItems {
200 = Blue Form
}
removeItems = 1,2,3
}
}
}
I have also tried to add a new layout field to the form configuration itself:
TYPO3:
CMS:
Form:
########### FORMEDITOR CONFIGURATION ###########
prototypes:
standard:
########### DEFAULT FORM ELEMENT DEFINITIONS ###########
formElementsDefinition:
Form:
formEditor:
editors:
9000:
identifier: 'layout'
group: select
templateName: 'Inspector-SingleSelectEditor'
label: 'Layout'
propertyPath: 'properties.layout'
selectOptions:
0:
value:
label: Normal
1:
value: form--blue
label: Blau
This works great in the backend but is leading to an The options "properties" were not allowed error in the frontend as properties for the form element are hardcoded in typo3/sysext/form/Classes/Domain/Model/FormDefinition.php:382.
Any ideas how to add a layout selection here? Best would be on the content element, as this would allow me to use the same form configuration with different layouts instead off making a duplicate form configuration which only distinguish in the layout.
The content object data is available in the Generic-Template from fluid_styled_content. Here you can check if the Ctype is 'form_formframework' and wrapping the form with your css class.
<f:if condition="{content}">
<f:then>
{content -> f:format.raw()}
</f:then>
<f:else>
<f:if condition="{data.CType} == 'form_formframework'">
<f:then>
<div class="{data.layout}">
<f:cObject typoscriptObjectPath="tt_content.{data.CType}.20" data="{data}" table="tt_content"/>
</div>
</f:then>
<f:else>
<f:cObject typoscriptObjectPath="tt_content.{data.CType}.20" data="{data}" table="tt_content"/>
</f:else>
</f:if>
</f:else>
</f:if>
We can add the fluid template layout like this({f:if(condition:'{data.layout}',then:'blue')}), in to default fluid_style_content/Resource/Private/Layouts/default.html (we Can override the fluid template in our site template) - without thinking for override the finisher and Flexform values of form:
<f:if condition="{data.CType} == 'form_formframework'">
<f:then>
<section id="c{data.uid}" class="form-section {f:if(condition:'{data.layout}',then:'blue')}">
<f:if condition="{data._LOCALIZED_UID}">
<a id="c{data._LOCALIZED_UID}"></a>
</f:if>
<f:render section="Before" optional="true">
<f:render partial="DropIn/Before/All" arguments="{_all}" />
</f:render>
<f:render section="Header" optional="true">
<f:render partial="Header/All" arguments="{_all}" />
</f:render>
<f:render section="Main" optional="true" />
<f:render section="Footer" optional="true">
<f:render partial="Footer/All" arguments="{_all}" />
</f:render>
<f:render section="After" optional="true">
<f:render partial="DropIn/After/All" arguments="{_all}" />
</f:render>
</section>
</f:then>
<f:else>
<div id="c{data.uid}" class="frame frame-{data.frame_class} frame-type-{data.CType} frame-layout-{data.layout}{f:if(condition: data.space_before_class, then: ' frame-space-before-{data.space_before_class}')}{f:if(condition: data.space_after_class, then: ' frame-space-after-{data.space_after_class}')}">
<f:if condition="{data._LOCALIZED_UID}">
<a id="c{data._LOCALIZED_UID}"></a>
</f:if>
<f:render section="Before" optional="true">
<f:render partial="DropIn/Before/All" arguments="{_all}" />
</f:render>
<f:render section="Header" optional="true">
<f:render partial="Header/All" arguments="{_all}" />
</f:render>
<f:render section="Main" optional="true" />
<f:render section="Footer" optional="true">
<f:render partial="Footer/All" arguments="{_all}" />
</f:render>
<f:render section="After" optional="true">
<f:render partial="DropIn/After/All" arguments="{_all}" />
</f:render>
</div>
</f:else>
</f:if>
I hope it helpful to all!

Why my DataProcessing\MenuProcessor don't show level-3 and level-4 for my page tree

I use Bootstrap_package v10 and Typo3 9, the menu processor doesn't show the level-3 and 4 for my pagetree.
I'm using the original templates from bootstrap package, the code is below:
10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
10 {
levels = 5
special = directory
special.value = 26969
expandAll = 1
includeSpacer = 1
as = mainnavigation
dataProcessing {
10 = TYPO3\CMS\Frontend\DataProcessing\FilesProcessor
10 {
references.fieldName = nav_icon
as = icon
if {
isTrue.stdWrap.cObject = COA
isTrue.stdWrap.cObject {
10 = TEXT
10.value = 1
10.if.isTrue = {$page.theme.navigation.icon.enable}
20 = TEXT
20.value = 1
20.if.isTrue = {$page.theme.navigation.dropdown.icon.enable}
}
}
}
}
}
and this is the fluid code :
<f:section name="MainNavigation">
<f:if condition="{menu}">
<ul class="navbar-nav">
<f:for each="{menu}" as="item">
<f:if condition="{item.spacer}">
<f:then>
</ul>
<ul class="navbar-nav">
</f:then>
<f:else>
<li class="nav-item{f:if(condition: item.active, then:' active')}{f:if(condition: item.children, then:' dropdown dropdown-hover')}">
<a href="{item.link}" id="nav-item-{item.data.uid}" class="nav-link{f:if(condition: item.children, then:' dropdown-toggle')}"{f:if(condition: item.target, then: ' target="{item.target}"')} title="{item.title}"{f:if(condition: item.children, then:' aria-haspopup="true" aria-expanded="false"')}>
<f:if condition="{theme.navigation.icon.enable} && {item.icon}">
<span class="nav-link-icon">
<f:if condition="{item.icon.0.extension} === svg">
<f:then>
<bk2k:inlineSvg image="{item.icon.0}" width="{theme.navigation.icon.width}" height="{theme.navigation.icon.height}" />
</f:then>
<f:else>
<f:image image="{item.icon.0}" alt="{item.icon.0.alternative}" title="{item.icon.0.title}" width="{theme.navigation.icon.width}" height="{theme.navigation.icon.height}" />
</f:else>
</f:if>
</span>
</f:if>
<span class="nav-link-text">{item.title}<f:if condition="{item.current}"> <span class="sr-only">(current)</span></f:if></span>
</a>
<f:if condition="{item.children}">
<ul class="dropdown-menu" aria-labelledby="nav-item-{item.data.uid}">
<f:for each="{item.children}" as="child">
<f:if condition="{child.spacer}">
<f:then>
<li class="dropdown-divider"></li>
</f:then>
<f:else>
<li>
<a href="{child.link}" class="dropdown-item{f:if(condition: child.active, then:' active')}"{f:if(condition: child.target, then: ' target="{child.target}"')} title="{child.title}">
<f:if condition="{theme.navigation.dropdown.icon.enable} && {child.icon}">
<span class="dropdown-icon">
<f:if condition="{child.icon.0.extension} === svg">
<f:then>
<bk2k:inlineSvg image="{child.icon.0}" width="{theme.navigation.dropdown.icon.width}" height="{theme.navigation.dropdown.icon.height}" />
</f:then>
<f:else>
<f:image image="{child.icon.0}" alt="{child.icon.0.alternative}" title="{child.icon.0.title}" width="{theme.navigation.dropdown.icon.width}" height="{theme.navigation.dropdown.icon.height}" />
</f:else>
</f:if>
</span>
</f:if>
<span class="dropdown-text">{child.title}<f:if condition="{child.current}"> <span class="sr-only">(current)</span></f:if></span>
</a>
</li>
</f:else>
</f:if>
</f:for>
</ul>
</f:if>
</li>
</f:else>
</f:if>
</f:for>
</ul>
</f:if>
</f:section>
The fluid is calling a page child but i don't know if it is recursive or not so it can showa all levels, what am I missing there, it seems like i'm the first one that having this issue ?
Thanks in advance for any help.
First you should verify if the data is available for more than the first two levels:
insert a <f:debug title="mainnavigation">{mainnavigation}</f:debug> in your template.
Then inspect your templates whether they are ready to display more than two levels.
I can imagine your templates show the first level, for second level a partial is called, but that partial does not call itself if necessary.
Except if you need some level specific markup (e.g. 'class="level1") you can build up menus by stacking the levels inside each other (giving stacked uls). So you either have a recursive call with stacked menus of the same markup or you define a partial for each level with individual markup (or you define a variable which contains the current level and call the partial recursive).
it's even worse: both levels are written out in the same template file, no partial (or section) is used.
I would change it to:
(I stayed with one file and instead of an additional partials I call a section, which can be in the same file)
<f:section name="MainNavigation">
<f:if condition="{menu}">
<ul class="navbar-nav">
<f:for each="{menu}" as="item">
<f:render section="subLevel" arguments="{item:item}" />
</f:for>
</ul>
</f:if>
</f:section>
<f:section name="subLevel">
<f:if condition="{item.spacer}">
<f:then>
<li class="dropdown-divider"></li>
</f:then>
<f:else>
<li class="nav-item{f:if(condition: item.active, then:' active')}{f:if(condition: item.children, then:' dropdown dropdown-hover')}">
<a href="{item.link}" id="nav-item-{item.data.uid}" class="nav-link{f:if(condition: item.children, then:' dropdown-toggle')}"{f:if(condition: item.target, then: ' target="{item.target}"')} title="{item.title}"{f:if(condition: item.children, then:' aria-haspopup="true" aria-expanded="false"')}>
<f:if condition="{theme.navigation.icon.enable} && {item.icon}">
<span class="nav-link-icon">
<f:if condition="{item.icon.0.extension} === svg">
<f:then>
<bk2k:inlineSvg image="{item.icon.0}" width="{theme.navigation.icon.width}" height="{theme.navigation.icon.height}" />
</f:then>
<f:else>
<f:image image="{item.icon.0}" alt="{item.icon.0.alternative}" title="{item.icon.0.title}" width="{theme.navigation.icon.width}" height="{theme.navigation.icon.height}" />
</f:else>
</f:if>
</span>
</f:if>
<span class="nav-link-text">{item.title}<f:if condition="{item.current}"> <span class="sr-only">(current)</span></f:if></span>
</a>
<f:if condition="{item.children}">
<ul class="dropdown-menu" aria-labelledby="nav-item-{item.data.uid}">
<f:for each="{item.children}" as="child">
<f:render section="subLevel" arguments="{item:child}" />
</for>
</ul>
</f:if>
</li>
</f:else>
</f:if>
</f:section>
Notice the changed markup for spacer in the first level!
Further changes might occur as I have not compared the code but concentrated on building up clean markup.
Increasing a 'parameter' for the recursion.
for an increasing value (level1, level2, level3...) you need a viewhelper in TYPO3 prior version 9:
this viewhelper can be realised in typoscript:
lib.math = TEXT
lib.math {
current = 1
prioriCalc = 1
}
then you can change the initial call to the SubLevel section to:
<f:render section="subLevel" arguments="{item:item,level:1}" />
Now you have a fluid variable level with the value 1.
the recursive call must be changed to:
<f:render section="subLevel" arguments="{item:child,level:{f:cObject(typoscriptObjectPath:'lib.math', data:'{level}+1')}}" />
for increasing values 2, 3, 4 ...
By default, MenuProcessor does not expand all levels. It will only show the branch you're on up to the level below the level you are on. If you want to show all levels for all branches you have to add expandAll = 1 to your configuration:
10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
10 {
levels = 5
expandAll = 1
...
}
Your Fluid template shows only 2 levels. By default in the Bootstrap package, you have a 2-level menu.
If you want to have more, you need to adjust the template to render more levels.
Here is the rendering of level 2 in your template:
<f:for each="{item.children}" as="child">
<f:render section="subLevel" arguments="{item:child}" />
</f:for>
If you want to render level 3, you need to go to the section subLevel and check if there are children of every item you set in arguments.
Example:
<f:if condition="{item.children}">
<ul>
<f:for each="{item.children}" as="level3Item">
...
</f:for>
</ul>
</f:if>
You should have some CSS for 5 levels of course. :)
I hope I could help you.
For levels beyond 2, I find it much easier to build in typoscript in your setup.typoscript.
lib.textmenu {
# We define the first level as text menu.
1 = TMENU
# The first level of this menu. 0 is rootline. -1 is 1 level up from rootline. 1 is 1 level down from rootline
entryLevel = 0
# UID's to exclude from the menu. Change this for each subsite, but will require a new template on each subsite.
excludeUidList = 21
# Turn spacers on, I use them to do sections of my menu.
1.SPC = 1
1.SPC.allWrap = <li class="a nav-item dropdown text-light bg-secondary SPC">|</li>
# Expand the whole menu - ie a sitemap
1.expAll = 1
# We define the normal state ("NO").
1.NO = 1
1.NO.wrap = <li class="nav-item NO">|</li>
1.NO.linkWrap = <li class="nav-item NO">|</li>
1.NO.ATagParams = class="nav-item dropdown NO"
# We define the active state ("ACT").
1.ACT = 1
1.ACT.wrapItemAndSub = <li class="nav-item active ACT">|</li>
# Get level 2 to get the format from level 1
2 <.1
# Do some customization for level 2
2.CUR = 1
2.CUR.wrapItemAndSub = <li class="nav-item dropdown active level2CUR">|</li>
2.CUR.ATagParams = class="active text-white"
# Make Levels 3 to 6 the same as level 1. I'll leave it to you to study all the typoscript wrapping.
3 < .1
4 < .1
5 < .1
6 < .1
}
Hello #Mohamed Masmoudi!
I am a newbie with TYPO3. I was asking myself the same question like you.
After a lot of research I found a solution which works for me (TYPO3 v10.4.12 and bootstrap-package) at least in desktop view mode.
But I don't understand what exactly is happening in mobile view. Maybe someone can give me a hint???
The sublevel is existing in source-code but is not showing up in mobile view.
First step was to modify the MenuProcessor in setup.typoscript
##########################
### DATA PREPROCESSING ###
##########################
dataProcessing {
1 = BK2K\BootstrapPackage\DataProcessing\ConstantsProcessor
1 {
as = theme
key = page.theme
}
10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
10 {
#modify these lines
levels = 5
expandAll = 1
includeSpacer = 1
as = mainnavigation
Second step modify the
/bootstrap_package/Resources/Private/Partials/Page/Navigation/Main.html
by adding the following lines to the fluid-template directly after the
<a href="{child.link}" class="dropdown-item{f:if(condition: child.active, then:' active')}"{f:if(condition: child.target, then: ' target="{child.target}"')} title="{child.title}">
...
</a>
here it comes:
<!-- 3rd Level -->
<ul class="dropdown-menu dropdown2-menu">
<f:for each="{child.children}" as="child2">
<li>
<a href="{child2.link}" class="dropdown-item{f:if(condition: child2.active, then:' active')}"{f:if(condition: child2.target, then: ' target="{child2.target}"')} title="{child2.title}">
<f:if condition="{theme.navigation.dropdown.icon.enable} && {child.icon}">
<span class="dropdown-icon">
<f:if condition="{child.icon.0.extension} === svg">
<f:then>
<bk2k:inlineSvg image="{child.icon.0}" width="{theme.navigation.dropdown.icon.width}" height="{theme.navigation.dropdown.icon.height}" />
</f:then>
<f:else>
<f:image additionalAttributes="{loading: 'lazy'}" image="{child.icon.0}" alt="{child.icon.0.alternative}" title="{child.icon.0.title}" width="{theme.navigation.dropdown.icon.width}" height="{theme.navigation.dropdown.icon.height}" />
</f:else>
</f:if>
</span>
</f:if>
<span class="dropdown2-text">{child2.title}<f:if condition="{child2.current}"> <span class="sr-only">(current)</span></f:if></span>
</a>
</li>
</f:for>
</ul>
<!-- End of 3rd Level -->
As you see I added a child2. You can add further sublevels like child3 etc by adding them after the particular <a>...</a>-tag
Don't forget to close all the open tags.
To separate the new sublevels by CSS I added a dropdown2-menu-Class to the tag.
Now you can add for example a .dropdown2-menu {margin-left: 50px} to your CSS.
Of course it is better not to touch the Bootstrap-Package. Instead use your own sitepackage. You can build one # https://sitepackagebuilder.com/
All of this is only to remember myself, what I was doing and maybe to help others... :-)

TYPO3 9.5.0 - pageUid of f:link.page not reading t3://page?uid=80

I have a TYPO3 9.5.0LTS and use the bootstrap package theme. It seems to be all working ... except ... when I add a link (internal or external) to a carousel item ... nothing gets rendered. The other elements come out fine.
I looked in the CalltoAction.html ... and found out that pageUid of f:link.page is not reading t3://page?uid=80.
When I {records} ... I get link => 't3://page?uid=80' (16 chars)
And when I test in CalltoAction.html:
<p>{item.data.link}</p>
<f:if condition="{item.data.link}">
<f:link.page pageUid="1" class="carousel-item-button btn btn-primary" additionalAttributes="{draggable:'false'}">
<f:if condition="{item.data.button_text}">
<f:then>
<span>{item.data.button_text}</span>
</f:then>
<f:else>
<span><f:translate key="readmore" extensionName="bootstrap_package" /></span>
</f:else>
</f:if>
</f:link.page>
</f:if>
<f:if condition="{item.data.link}">
<f:link.page pageUid="{item.data.link}" class="carousel-item-button btn btn-primary" additionalAttributes="{draggable:'false'}">
<f:if condition="{item.data.button_text}">
<f:then>
<span>{item.data.button_text}</span>
</f:then>
<f:else>
<span><f:translate key="readmore" extensionName="bootstrap_package" /></span>
</f:else>
</f:if>
</f:link.page>
</f:if>
I get the following result in the FE:
<p>t3://page?uid=80</p>
<a draggable="false" class="carousel-item-button btn btn-primary" href="/"><span>Read more</span></a>
<span>Read more</span>
So pageUid of f:link.page not reading t3://page?uid=80
How can I solve this?
the f:link.page-VH expects an integer (uid) in the parameter pageUid.
t3://page?uid=80 by way is no integer but a string. A special string which can be handled by the f:link.typo3link-VH

Listing files and folders with TYPO3 extbase fluid?

I have files array like
'file1.pdf',
'file2.pdf',
'file3.JPG',
'Folder1/file1.pdf',
'Folder1/Subfolder1/Subfolder-file1.txt',
'Folder2/text.txt',
'Folder2/file2.pdf'
For get list of files and folder I use following fluid
<f:for each="{files}" as="userFile">
<f:if condition="{userFile -> myext:explode(delimiter:'/') -> f:count()} == 1">
<f:then>
{userFile}<br />
</f:then>
<f:else>
<div class="folder">
<f:for each="{userFile -> myext:explode(delimiter:'/')}" as="segment" iteration="itemIteration">
<f:if condition="{itemIteration.isFirst}">
<f:then>{segment}</f:then>
<f:else>{segment}<br /></f:else>
</f:if>
</f:for>
</div>
</f:else>
</f:if>
</f:for>
I'm using my own explode view helper
And I get only list files and folders
file1.pdf
file2.pdf
file3.JPG
<div class="folder">Folder1</div>
file1.pdf
<div class="folder">Folder1</div>
<a href="">Subfolder1
Subfolder-file1.txt
<div class="folder">Folder2</div>
text.txt
<div class="folder">Folder2</div>
file2.pdf
How I can get listing like with fluid?
file1.pdf
file2.pdf
file3.JPG
<div class="folder">Folder1</div>
file1.pdf
Subfolder-file1.txt
Subfolder-file1.txt
<div class="folder">Folder2</div>
text.txt
file2.pdf
Is it possible?
In your Extbase Controller you can use the TYPO3\CMS\Core\Resource\ResourceFactory to get folders:
$resourceFactory = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance();
// Format [ID OF STORAGE]:[FOLDER]
$folder = $resourceFactory->getFolderObjectFromCombinedIdentifier('1:my/directory/to/scan');
$this->view->assign('folder', $folder);
Now you can use folowing partial in your fluid to walk the folders:
Partial/FolderRecusive.html
<f:for each="{folder.files}" as="file">
<a href={file.publicUrl}>{file.name}</a>
</f:for>
<f:for each={folder.subFolders} as="subFolder">
<f:if condition="{subFolder.files -> f:count()} > 0 OR {subFolder.subFolders -> f:count()} > 0">
<div class="folder">{subFolder.name}</div>
<f:render partial="FolderRecursive" arguments="{folder:subFolder}" />
</f:if>
</f:for>
In your Template put something like this to display the folders:
<f:render partial="FolderRecursive" arguments="{folder:folder}" />

how to: find the length of a typoscript defined array in fluid?

I define an array in my extensions setup.txt typoscript like so:
settings{
halls {
0 = Default
1 = Mississauga
2 = Halifax
3 = Niagara Falls
4 = Oakville
5 = Pickering
}}
how in my fluid template can I find the length of the halls array? I want an if condition to do one thing if length is greater than 1 and another if not.
I am using typo3 v4.5.32 with extbase 1.3.
Thank you.
I tried this but it puts out two <th> tags instead of just one. The first if is meant to prove that there is more than one element, the next is meant to print out a <th> only if it is the first element.
<f:for each="{settings.halls}" as="hall" key="number" iteration="itemIteration">
<f:if condition="{itemIteration.isFirst != itemIteration.isLast}">
<f:if condition="{itemIteration.index == 0}">
<th>
<f:translate key="tx_bpscoupons_domain_model_coupon.hall" />
</th>
</f:if>
</f:if>
</f:for>
Why?
UPDATE: here is my work around for a lack of "is array length > 1" ferature in fluid
<f:for each="{settings.halls}" as="hall" key="number" iteration="itemIteration">
<f:if condition="{itemIteration.isFirst}">
<f:then>
<f:if condition="{itemIteration.isLast}">
// if both first and last there is only one so skip
</f:if>
</f:then>
<f:else>
<f:if condition="{itemIteration.isLast}">
//if there is more than one element in halls then eventually you'll get here once so print out th tags
<th>
<f:translate key="tx_bpscoupons_domain_model_coupon.hall" />
</th>
</f:if>
</f:else>
</f:if>
</f:for>
and to print out data:
<f:for each="{settings.halls}" as="hall" key="number" iteration="itemIteration">
<f:if condition="{itemIteration.isFirst}">
<f:then>
<f:if condition="{itemIteration.isLast}">
<f:then>
</f:then>
<f:else>
<f:if condition="{number} == {coupon.hall}">
<td>{hall}</td>
</f:if>
</f:else>
</f:if>
</f:then>
<f:else>
<f:if condition="{number} == {coupon.hall}">
<td>{hall}</td>
</f:if>
</f:else>
</f:if>
</f:for>
ugly but seems to work.
UPDATE 2 :
DOH!!! I missed total, just what I needed but I was looking for length or count, so this code is what I want:
<f:for each="{settings.halls}" as="hall" key="number" iteration="itemIteration">
<f:if condition="{itemIteration.total} > 1">
<f:if condition="{itemIteration.isLast}">
<th><f:translate key="tx_bpscoupons_domain_model_coupon.hall" /></th>
</f:if>
</f:if>
</f:for>
You can find a length of an array with the f:count ViewHelper. Just like other ViewHelper it can be used as an inline notation (You can find more here)
The correct code would be:
<f:if condition="{settings.halls -> f.count()} > 1">
<f:then>
//your code for then
</f:then>
<f:else>
//your code for else
</f:else>
</f:if>
<f:if condition="{f:count(subject: settings.halls)} > 1"> do something </f:if>
see update#2 above for the answer. to reiterate:
<f:for each="{settings.halls}" as="hall" key="number" iteration="itemIteration">
<f:if condition="{itemIteration.total} > 1">
<f:if condition="{itemIteration.isLast}">
<th><f:translate key="tx_bpscoupons_domain_model_coupon.hall" /></th>
</f:if>
</f:if>
</f:for>
For those of you who are looking for a custom viewhelper for this:
class ArrayCountViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
/**
* Get array count
*
* #param mixed $array
* #return string
*/
public function render($array) {
if (!is_array($array))
return 0;
return count($array);
}
}