I have a fluid typo3 site with single page layout.One menu have different layout.How to get the selected layout name in my main template?
main.html
<v:page.menu levels="1" as="sections">
<f:for each="{sections}" as="section" iteration="itemIteration">
<f:debug>{sections}</f:debug>
</f:for>
</v:page.menu>
sub.html
<f:layout name="Pagewithnav" />
<f:section name="Configuration">
<flux:form id="subnav" icon="{f:uri.resource(path: 'Icons/Page/logo.png')}" label="Sub Navigation">
<!-- Insert fields, sheets, grid, form section objects etc. here, in this flux:form tag -->
</flux:form>
<flux:grid>
<!-- Edit this grid to change the "backend layout" structure -->
<flux:grid.row>
<flux:grid.column colPos="0" colspan="4" name="main" label="Navigation wrapper" />
</flux:grid.row>
<flux:grid.row>
<flux:grid.column colPos="1" colspan="4" name="main" label="Main wrapper" />
</flux:grid.row>
</flux:grid>
</f:section>
<f:section name="Main">
<div class="sub_nav">
<div class="container">
<v:content.render column="0"/>
</div>
</div>
<div class="container">
<v:content.render column="1"/>
</div>
</f:section>
It depends on what exactly you mean by "Layout name":
If you mean fields of the pages table for each individual page then those will be available in each record when you iterate it in v:page.menu (for example, tx_fed_page_controller_action).
If you mean fields of pages but also when this variable is inherited (for example, backend_layout is and tx_fed_page_controller_action is as well, but each through different methods) it becomes more complex: you would need to walk through the root line and use the first non-empty value. For that, v:page.rootLine plus v:iterator.filter plus v:iterator.first can be of great help (put output from root line into filter to remove non-empty values then use the first VH to select the first value from that filtered result).
If you define this "layout" in a Flux form field on your page template it becomes a FlexForm variable which you can read with flux:form.data (with inheritance if not disabled and if templates match up through root line).
Depending on exactly which you mean there are quite a few possible solutions. If you are also looking for a recommendation about which one it makes sense to use: most likely you mean the layout you select in page properties (regardless of field) and for this, v:page.rootLine plus v:iterator.filter plus v:iterator.first is a nice and generic method to "slide select" any non-empty value from the root line of the current page.
You can get it with a variable in fluid
lib.templateName = TEXT
lib.templateName.stdWrap.cObject = CASE
lib.templateName.stdWrap {
cObject = TEXT
cObject {
data = levelfield:-2,backend_layout_next_level,slide
override.field = backend_layout
split {
token = pagets__
1.current = 1
1.wrap = |
}
}
ifEmpty = Default
}
page = PAGE
page.10 = FLUIDTEMPLATE
page.10 {
#...
variables.templateName < lib.templateName
}
Related
I am trying to get an Image from a custom content element into my fluid template. To achieve this I am using FilesProcessor.
custom element
Here is the corresponding code snippet from my setup.typoscript:
tt_content {
heiner_newcontentelement =< lib.contentElement
heiner_newcontentelement {
templateName = Default
dataProcessing.10 = TYPO3\CMS\Frontend\DataProcessing\FilesProcessor
dataProcessing.10 {
as = images
references.fieldName = image
references.table = tt_content
sorting = title
sorting.direction = descending
}
}
}
Showing what's available via f:debug-Viewhelper provides the following:
available variables in fluid template
So far, so good, what I have tried was to simply output the image in my fluid template with the following code:
<html data-namespace-typo3-fluid="true" xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"></html>
<f:layout name="Default" />
<f:section name="content">
<ul class="Das ist gut">
<f:for each="{images}" as="image">
<f:debug>{image}</f:debug>
<f:image image="{image}" height="250c" width="200c"/>
</f:for>
</ul>
</f:section>
</html>
although the variable "image" in the for-each loop is not empty, the image-viewhelper wont render anything. I am so desperate :( Somebody knows whats going wrong here? A lot of thx :)
According to the documentation, File Reference information are not always available in the fluidtemplate (see also https://docs.typo3.org/m/typo3/reference-coreapi/9.5/en-us/ApiOverview/Fal/UsingFal/Frontend.html#fluidtemplate).
What happens if you try this:
<ul class="Das ist gut">
<f:for each="{images}" as="image">
<f:debug>{image}</f:debug>
<f:image image="{image.originalFile}" height="250c" width="200c"/>
</f:for>
</ul>
I setup a TYPO3 website with News System Ext. and I need to add the category ID to the entry class on the file : fileadmin\templates\ext\news\Templates\News\Detail.html
so, the final output will be as follows
<div class="entrys category-uid-[id here]"></div>
There is a little difference if you want just the first category or all categories.
<f:section name="firstCatClass">
<f:for each="categories" as="category" iteration="iterator"><f:if condition="{iterator.isFirst}"> category-uid-{category.uid}</f:if></f:for>
</f:section>
<f:section name="allCatClasses">
<f:for each="categories" as="category"> category-uid-{category.uid}</f:for>
</f:section>
then you can insert this in the class-parameter of your divtag.
<div class="entrys{f:render(section:'allCatClasses', arguments:'{categories:item.categories}')}">
for only the first category there already is a handling in the partial List/Item.html which you can modify to:
<div class="entrys{f:if(condition:newsItem.firstCategory, then:' category-uid-{newsItem.firstCategory}')}">
Is there a way to have the Frontend layout determine the Backend layout, template file and columns?
At the moment I have the following code that allows you to set the Backend layout and it uses the appropriate template file. But this gets very messy when there are different column positions for each layout.
page.10 = FLUIDTEMPLATE
page.10 {
#format = html
file= fileadmin/templates/example/partials/example_home.html
partialRootPath = fileadmin/templates/example/partials/
layoutRootPath = fileadmin/templates/example/layouts/
variables {
# Assign the Columns
main < styles.content.get
main.select.where = colPos = 0
news < styles.content.get
news.select.where = colPos = 1
}
}
}
# Assign the Template files with the Fluid Backend-Template
page.10.file.stdWrap.cObject = CASE
page.10.file.stdWrap.cObject {
key.data = levelfield:-1, backend_layout_next_level, slide
key.override.field = backend_layout
# Set the default Template
default = TEXT
default.value = fileadmin/templates/example/partials/example_home.html
# Set a second Template
23 = TEXT
23.value = fileadmin/templates/example/partials/example_internal.html
}
Not messy at all, here's a real world example:
page.10 = FLUIDTEMPLATE
page.10 {
file.stdWrap.cObject = CASE
file.stdWrap.cObject {
key.data = pagelayout
default = TEXT
default.value = {$customPagesTemplatePath}/Standard.html
1 = TEXT
1.value = {$customPagesTemplatePath}/Home.html
2 = TEXT
2.value = {$customPagesTemplatePath}/Landing.html
10 = TEXT
10.value = {$customPagesTemplatePath}/NewsDetail.html
11 = TEXT
11.value = {$customPagesTemplatePath}/LandingMini.html
12 = TEXT
12.value = {$customPagesTemplatePath}/FullWidth.html
}
layoutRootPath = {$customPagesLayoutPath}
partialRootPath = {$customPagesPartialPath}
}
Think about it like this:
As you say, forget about frontend layout. That's legacy; be layout serves for BE and FE.
If a page was a city, the colPos would be the street. Or rather, imagine the Backend is a map you're drawing, and the frontend is a LEGO City you build according tho that map :-)) If it's OK, I'll stick with that metaphor.
ColPos is a determined part of a page where a record lives. If you can, take a look at the tt_content table in the database: you'll see that colPos is just a column with a number. So in the city "Page 1", there's a street called "colPos 7", and it contains some records (those would be houses). With the be_layout wizard in TYPO3 you'll create an administrative map of that city: how the editor should see these streets.
In the FLUIDTEMPLATE you call depending on the selected be_layout, you will create the city itself; the rendered frontend.
Here's another real world example for such a fluid template (Home.html):
<f:render partial="Mobilenav" />
<f:render partial="Header"/>
<div class="row">
<f:cObject typoscriptObjectPath="lib.home-teaser" />
</div>
<aside>
<div class="row">
<div class="columns">
<div class="row">
<div class="fp-teaser-outer small-48 medium-24 large-12 columns">
<div class="fp-teaser-box-wrapper">
<f:cObject typoscriptObjectPath="lib.home-something" />
</div>
</div>
<div class="fp-teaser-outer small-48 medium-24 large-12 columns">
<div class="fp-teaser-box-wrapper">
<f:cObject typoscriptObjectPath="lib.home-somethingelse" />
</div>
</div>
<div class="fp-teaser-outer small-48 medium-24 large-12 columns">
<div class="fp-teaser-box-wrapper">
<div class="fp-teaser-box">
<f:cObject typoscriptObjectPath="lib.home-news-plugin-title" />
<div class="fp-teaser-hr"></div>
<div class="fp-teaser-content">
<f:cObject typoscriptObjectPath="lib.home-news" />
</div>
</div>
</div>
</div>
<div class="fp-teaser-outer small-48 medium-24 large-12 columns">
<div class="fp-teaser-box-wrapper">
<div class="fp-teaser-box">
<f:cObject typoscriptObjectPath="lib.home-blog-plugin-title" />
<div class="fp-teaser-hr"></div>
<div class="fp-teaser-content">
<f:cObject typoscriptObjectPath="lib.home-blog" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</aside>
<f:render partial="Footer"/>
... well, but where's the correlation with the colPos?
Nowhere yet! I (while being positive that there are other approaches) do this in TypoScript:
lib.home-something < styles.content.get
lib.home-something {
select.where = colPos = 7
}
So by this we prepare content for the fluid template: get all content of that page's column 7 (using the extension fluid_styled_content) and put it into a "lib" content object.
That's then inserted into the page via the f:cObject viewhelper:
<f:cObject typoscriptObjectPath="lib.home-something" />
Like this, all houses in 7th street are put into the city in exactly this location – and thus rendered in your page.
Programmatically,
$backendLayout=$GLOBALS['TSFE']->cObj->getData('pageLayout');
If None was selected in the backend [-1], it will output 'none'.
If nothing was selected it will output 'default'. Otherwise it will output the correct backend layout prefixed with your extension, taking into account subpage layouts up the page ancestry chain.
I try to slide content elements at my TYPO3 Backend (v6.2) with Fluid Powered TYPO3. So I don't have CSS_Styled_content included. http://wiki.typo3.org/Content_Slide Example:
10 < styles.content.getRight
10.slide = -1
Especially I'd like to slide my content from the colPos=0 'Slider' to the Pages below. Is this possible with FLUID / FluidTYPO3 (FLUX)?
<f:section name="Configuration">
<flux:form id="fluidpage" options="{icon: 'typo3conf/ext/my_extension/Resources/Public/Icons/Page/Standard.gif'}">
</flux:form>
<flux:grid>
<flux:grid.row>
<flux:grid.column colPos="0" name="Slider" colspan="2" />
</flux:grid.row>
<flux:grid.row>
<flux:grid.column colPos="1" name="Left" />
<flux:grid.column colPos="2" name="Right" />
</flux:grid.row>
</flux:grid>
</f:section>
I try it like this ... but that's wrong.
styles.content.getSlider.slide = -1
You can do it in just the same way it is done in css_styled_content internally, using a CONTENT object:
lib.content_not_cascading_without_default = CONTENT
lib.content_not_cascading_without_default {
table = tt_content
# This enables content sliding. For more possible values
# check the docs (linked above)
slide = -1
select {
# Use the correct column position here
andWhere = colPos = 1
orderBy = sorting
languageField = sys_language_uid
}
}
Alternatively, if you use fluid to render the template, you can also render the content using the v:content.render-ViewHelper from EXT:vhs:
<v:content.render column="1" slide="-1"/>
I want to print the following HTML only if one or more of the colPos has content in it. If none have content elements in it, then I don't want to print this block (the whole "row") of HTML.
<div class="row">
<div class="col-sm-4">
<f:cObject typoscriptObjectPath="lib.dynamicContent" data="5" />
</div>
<div class="col-sm-4">
<f:cObject typoscriptObjectPath="lib.dynamicContent" data="6" />
</div>
<div class="col-sm-4">
<f:cObject typoscriptObjectPath="lib.dynamicContent" data="7" />
</div>
</div>
I thought about getting the colPos and try to do a OR condition on Fluid. But I have no idea on how to do it. I know I can check one by one like this:
<f:if condition="{f:cObject(typoscriptObjectPath: 'lib.dynamicContent', data: '5')}">
...HTML for colPos 5 HERE...
</f:if>
But I don't want to do that. In my template I have almost 50 different colPos and they are organized by blocks (rows). Like colPos 1 to 5 is one block(row). colPos 10 to 25 in another block(row). But some pages will not use some blocks (rows) of colPos, so there's no reason on printing the HTML code for those blocks (rows) of colPos unused.
Thanks for your help!
A fluid-only solution would be to assign the results of the <f:cObject>-ViewHelpers each to a variable, and then use the concatenation of these variables in a condition. The v:-namespace in the example is the namespace of the extension vhs:
<v:variable.set name="col-5" value="{f:cObject(typoscriptObjectPath: 'lib.dynamicContent', data: '5')}"/>
<v:variable.set name="col-6" value="{f:cObject(typoscriptObjectPath: 'lib.dynamicContent', data: '6')}"/>
<v:variable.set name="col-7" value="{f:cObject(typoscriptObjectPath: 'lib.dynamicContent', data: '7')}"/>
<f:if condition="{col-5}{col-6}{col-7}">
<div class="row">
<div class="col-sm-4">{col-5}</div>
<div class="col-sm-4">{col-6}</div>
<div class="col-sm-4">{col-7}</div>
</div>
</f:if>
You should of course move this stuff to a partial, which gets an array of the columns to print as a parameter. Then you need to write the logic only once.
Also, you should think again, if you really need 25 columns.
Since TYPO3 8.6, this is possible without extension "vhs":
<f:variable name="col-5">
<f:cObject typoscriptObjectPath="lib.dynamicContent" data="5" />
</f:variable>
<f:if condition="{col-5}">
<f:format.raw>{col-5}</f:format.raw>
</f:if>