How do I retrieve the layout field from the parent page? - typo3

I want to know what the layout of the parent page is in my fluid template.
So in the template I've added:
<f:cObject typoscriptObjectPath="lib.parentLayout" data="{uid: {data.pid}}" />
But I am not sure what to do in typoscript:
lib.parentLayout = CONTENT
lib.parentLayout {
table = pages
select {
uid.data = field:uid
fieldName = layout
}
}

There are different options to get that information.
You could for example add the field layout to the so called rootline fields https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/Configuration/Typo3ConfVars/FE.html#globals-typo3-conf-vars-fe-addrootlinefields and make use of the level functionality of getText:
lib.parentLayout = TEXT
lib.parentLayout {
data = levelfield:-2, layout
}
or you could use the PID (aka parent parent ID) to get the parent page with CONTENT:
lib.parentLayout = CONTENT
lib.parentLayout {
table = pages
select {
uidInList.field = pid
pidInList = 0
selectFields = layout
}
renderObj = TEXT
renderObj.field = layout
}
or with RECORDS:
lib.parentLayout = RECORDS
lib.parentLayout {
tables = pages
source.field = pid
conf.pages = TEXT
conf.pages {
field = layout
}
}
and of course you can go for setting UID with PID in the Fluid template, but IMHO this is misleading.

Related

How to integrate a html template to typo3

I'am new to typo3 and I want to integrate my HTML template in it. but I can't add my content to the pages threw the dashboard all I get is a blank page.
I'am using TYPO3 v8
Greetings!
The steps you need to do for template integration in TYPO3 8
TYPOSCRIPT
Tell TYPO3 by where the templates should be get.
page = PAGE
page.10 {
templateRootPaths {
10 = PATH TO YOUR TEMPLATES
}
layoutRootPaths {
10 = PATH TO YOUR LAYOUTS
}
partialRootPaths {
10 = PATH TO YOUR PARTIALS
}
templateName = TEXT
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 = Home
}
}
LAYOUTS
It's not required to create a layout, but i suggest to do it, also if you have just one type of template.
The layouts ( in TYPO3 called Backend Layouts ) can be created in TYPO3 backend and the backend layouts are saved in database. But you can save the backend layouts configuration in a file.
Hint: Try save the backend layouts configuration in files so you can add to
git
Example of backend layout configuration:
mod.web_layout.BackendLayouts {
Home # identified by this name {
title = Home # this is shown in backend when you select the layout
icon = EXT:example_extension/Resources/Public/Images/BackendLayouts/default.gif
config {
backend_layout {
colCount = 1
rowCount = 1
rows {
1 {
columns {
1 {
name = Content
colPos = 1 # this is important, i'm talking about colPos below
}
}
}
}
}
}
}
}
ColPos meaning: you can have multiple columns in a layout, and the colPos is used to render the content in frontend. This is what will be used later in template <f:cObject typoscriptObjectPath="lib.dynamicContent" data="{colPos: 1}" />
The above configuration should be included in PageTs. This is found if you edit a page and go to Resources tab.
Typoscript configuration of lib.dynamicContent
lib.dynamicContent = COA
lib.dynamicContent {
5 = LOAD_REGISTER
5 {
colPos.cObject = TEXT
colPos.cObject {
field = colPos
ifEmpty.cObject = TEXT
ifEmpty.cObject {
value.current = 1
ifEmpty = 0
}
}
pageUid.cObject = TEXT
pageUid.cObject {
field = pageUid
ifEmpty.data = TSFE:id
}
contentFromPid.cObject = TEXT
contentFromPid.cObject {
data = DB:pages:{register:pageUid}:content_from_pid
data.insertData = 1
}
wrap.cObject = TEXT
wrap.cObject {
field = wrap
}
maxItems.cObject = TEXT
maxItems.cObject {
field = maxItems
ifEmpty =
}
}
20 = CONTENT
20 {
table = tt_content
select {
includeRecordsWithoutDefaultTranslation = 1
orderBy = sorting
where = {#colPos}={register:colPos}
where.insertData = 1
pidInList.data = register:pageUid
pidInList.override.data = register:contentFromPid
max.data = register:maxItems
// select.languageField setting is needed if you use this typoscript in TYPO3 < v7
// languageField = sys_language_uid
}
stdWrap {
dataWrap = {register:wrap}
required = 1
}
}
90 = RESTORE_REGISTER
}
lib.dynamicContentSlide < lib.dynamicContent
lib.dynamicContentSlide.20.slide = -1
lib.dynamicContentFirst < lib.dynamicContent
lib.dynamicContentFirst.20.select.max = 1
Home layout html integration
<f:render section="main" />
Home template integration
<f:layout name="Home" />
<f:section name="content">
// content
<f:cObject typoscriptObjectPath="lib.dynamicContent" data="{colPos: 1}" />
</f:section>
Now we have the setup of layouts and templates. Hope that you have a basic setup of TYPO3 ( a root page at least and a template setup )
If you don't have this setup already, follow the next steps:
Create a root page
Go with list on root page
Create a Template record - go in Options tab and check Clear -> Constants and Clear -> setup and check also Rootlevel
Go in Includes tab and select from the multiple selectbox fluid_styled_content
Paste the TYPOSCRIPT configuration in the created template ( check General Tab )
Edit Root page and go to the Appearance tab to select the Backend Layout.

TYPO3 Menu Double up

I have this custom menu setup based on the default section menu. When testing on one content element, it looks good... When I add a second content element to the page both get added to each menu item.
Anyone know what's going on here?
tt_content.menu.20.3.1.sectionIndex.useColPos = -1
tt_content.menu.20.101 < tt_content.menu.20.3
tt_content.menu.20.101 {
1.NO {
stdWrap.cObject = CONTENT
stdWrap.cObject {
table = tt_content
select {
pidInList.field = uid
}
renderObj = COA
renderObj {
10 = FILES
10 {
stdWrap.wrap = <div class="menu-img">|</div>
references {
table = tt_content
fieldName = image
}
renderObj = IMAGE
renderObj {
file {
import.data = file:current:uid
treatIdAsReference = 1
width = 100c
height = 100c
}
altText.data = file:current:alternative
titleText.data = file:current:title
stdWrap.typolink.parameter.data = file:current:link
}
maxItems = 1
}
20 = TEXT
20.field = header
30 = TEXT
30.field = rowDescription
}
}
}
}
This is currently outputting:
<ul>
<li><img/>Heading1Desc1<img2/>Heading2Desc2</li>
<li><img/>Heading1Desc1<img2/>Heading2Desc2</li>
<ul>
What it should be:
<ul>
<li><img/>Heading1Desc1</li>
<li><img2/>Heading2Desc2</li>
</ul>
It is about your CONTENT object.
your selection is strange:
select {
pidInList.field = uid
}
you select all tt_content elements which are in the page with the uid of the current content element.
And your rendering is executed for each record found.
Do you really need to select the contentelement with a cObject again? I think in the menu it should be the current context.
add on:
I would try something like this to render the image before the text (which should be available by default):
before just for the image instead of stdWrap with a full query of all CEs and with a COA for all fields.
have a look to the correct fieldname!
1.NO {
before.cObject = FILES
before.cObject {
stdWrap.wrap = <div class="pic">|</div>
references {
table = tt_content
uid.data = uid
// 'image' or 'media' or ... ???
fieldName = image
}
renderObj = IMAGE
renderObj {
stdWrap.wrap = <div class="pic">|</div>
file {
import.data = file:current:uid
treatIdAsReference = 1
width = 150c
height = 150c
}
altText.data = file:current:alternative
titleText.data = file:current:title
#params = class="menu-img"
// don't do a link inside a link =:-O
#stdWrap.typolink.parameter.data = file:current:link
}
maxItems = 1
}
}
I have tried this many different ways and cannot get it working with the image and fields. So instead I have simply patched my original code using by adding: tt_content.menu.20.101.maxItems = 1 and adding a wrap to the renderObj.
I know this is not how it should be done, but it works for now. But if anyone knows the correct way of doing it let me know!

TYPO3: Backend Layout Condition in TypoScript

I'd like to change the way elements are rendered depending on the page's backend layout.
Changing the fluid styled content template depending on the backend layout works as following:
[globalVar = TSFE:page|backend_layout = 1][globalVar = TSFE:page|backend_layout = 2]
lib.fluidContent.templateRootPaths.10 = EXT:ds_res/Resources/Private/Templates/ContentTemplates/
[global]
If it's 1 or 2, then use the other templates.
However, this only works if the BE layout is set directly at the page and not when it's inherited from its parent.
How to fix this?
Running TYPO3 7.6.15
In TYPO3 7.5 "Backend Layout"-Conditions has been simplified with "pagelayout" in Typoscript. Example:
page.10 = FLUIDTEMPLATE
page.10 {
file.stdWrap.cObject = CASE
file.stdWrap.cObject {
key.data = pagelayout
default = TEXT
default.value = EXT:sitepackage/Resources/Private/Templates/Home.html
3 = TEXT
3.value = EXT:sitepackage/Resources/Private/Templates/1-col.html
4 = TEXT
4.value = EXT:sitepackage/Resources/Private/Templates/2-col.html
}
}
Instead of:
field = backend_layout
field.data = levelfield:-2,backend_layout_next_level,slide
field.ifEmpty = default
Maybe this also works in your conditions like this:
[globalVar = TSFE:page|pagelayout = 1]
However, you should not change the used template file with [xy]-conditions and prefer using a CASE shown in the example above. Each number is the UID of a backend_layout by the way.
In TYPO3 9.5+ you can use typoscript conditions like:
[page["backend_layout"] == 'pagets__2']
page.bodyTagCObject.value.wrap = <body id="uid|" class="fullpage">
[end]
Edit:
As Bernd has mentioned use backend_layout only if you need the real defined field. If you need the computed value (e.g. for a sub page getting its layout from the backend_layout_next_level from a parent page) use pagelayout with a case like:
bodyTagCObject = TEXT
bodyTagCObject.value.field = uid
bodyTagCObject.value.wrap.cObject = CASE
bodyTagCObject.value.wrap.cObject{
key.data = pagelayout
default = TEXT
default.value = <body id="uid|" class="standard">
pagets__2 = TEXT
pagets__2.value = <body id="uid|" class="fullpage">
}
We use this solution
page = PAGE
page.10 = FLUIDTEMPLATE
page.10 {
templateName = TEXT
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 = Index
}
layoutRootPaths {
10 = EXT:yourext/Resources/Private/Layouts
}
partialRootPaths {
10 = EXT:yourext/Resources/Private/Partials
}
templateRootPaths {
10 = EXT:yourext/Resources/Private/Templates
}
}
This approach is when u do not have the Backendlayouts in the DB (made through the backend) but include them from files. As there is no uid then you go by the templatename.
Example:
If you use this PageTS:
mod.web_layout.BackendLayouts {
Blankpage {
title = Blankpage
name = Blankpage
icon = EXT:yourext/Resources/Public/Icons/BackendLayouts/Blankpage.jpg
config {
backend_layout {
colCount = 1
rowCount = 2
rows {
1 {
columns {
1 {
name = Nameofthecolumn
colPos = 0
colspan = 1
}
}
}
2 {
columns {
1 {
name = Nameofthesecondcolumn
colPos = 1
colspan = 1
}
}
}
}
}
}
}
You will need a Template.html with the name Blankpage.html within your EXT-Templates.
So you can add more Templates and Backendlayouts without touching the TS again. Simply add PageTS and a html-template.
There is a feature available which avoids having that code duplicated
page.10 = FLUIDTEMPLATE
page.10 {
templateName = TEXT
templateName.stdWrap.cObject = CASE
templateName.stdWrap.cObject {
key.data = pagelayout
....
As you can not handle the inherited layouts in conditions you need to use typoscript. My solution is this:
page.10 = FLUIDTEMPLATE
page.10 {
templateRootPaths.1 = {$resDir}/Private/Templates
partialRootPaths.1 = {$resDir}/Private/Partials
layoutRootPaths.1 = {$resDir}/Private/Layouts
templateName = TEXT
templateName.cObject = CASE
templateName.cObject {
key.data = levelfield:-1, backend_layout_next_level, slide
key.override.field = backend_layout
#Default Template
default = TEXT
default.value = subpage
# homepage
pagets__homepage = TEXT
pagets__homepage.value = homepage
pagets__subpage = TEXT
pagets__subpage.value = subpage
}
variables {
:
pageLayout = TEXT
pageLayout.data = levelfield:-1, backend_layout_next_level, slide
pageLayout.override.field = backend_layout
// since TYPO3 7 this already is computed by the core and this gives the same:
pageLayout = TEXT
pageLayout.data = pagelayout
:
}
}
Avoid using file for better implementation with ..RootPaths.
As we use backendlayouts defined in files (which gets included in the pageTSconfig) the key names starting with pagets__, you also might use the numbers of backend_layout records.
I use the constant {$resDir} to define the root of resources which can be changed in an easy way. In a siteextension this could be:
resDir = EXT:site_project1/Resources
I also define a fluid variable with the currently active page layout for further differentiation in the templates.
If you want the ...RootPaths to be different for each layout you need to build cObject with a CASE obejct similar to my selection of the template name.
In general: all this could be handled in the fluid templates if you have the backend layout available in your variables: you only need to have one starting template, which calls a layout where all further calls to partials are individualized by the current layout like
<f:render partial="{pageLayout}/header" arguments="{_all}" />
TYPO3 11.x:
[tree.pagelayout == 2]
...
[global]
https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/11.0/Feature-88276-TypoScriptConditionForPageLayout.html

TYPO3 TypoScript: Display a list of subpages with content on parent page

I am trying to create an archive page that displays a list of subpages, similar to WordPress but display the parent's subpages instead of posts. I want the archive page to include the following from the subpage:
Title
First image
First 150 words of regular text element
At the moment I can display a page title, but that's where I got stuck. I am placing the code in a sub template. Here is the code.
lib.portfoliolist = CONTENT
lib.portfoliolist.table = pages
lib.portfoliolist.select {
pidInList = this
}
lib.portfoliolist.renderObj = COA
lib.portfoliolist.renderObj {
stdWrap.wrap = <div class="project">|</div><hr />
10 = TEXT
10 {
field = title
wrap = <h2>|</h2>
10.typolink.parameter.field = uid
}
}
If it helps, all of the images are within the fileadmin/user_upload/ directory, and this is my page structure:
Root
Home
About
Project Portfolio
Project 1
Project 2
Blog
Contact Us
Seems like I figured it out myself, all I had to do was call for content in a separate query. For those that are looking to achieve something similar, here is the code I used to help you out.
lib.portfoliolist = CONTENT
lib.portfoliolist.table = pages
lib.portfoliolist.select {
orderBy = sorting ASC
}
lib.portfoliolist.renderObj = COA
lib.portfoliolist.renderObj {
stdWrap.allWrap = <div class="row">|</div>
stdWrap.wrap = <div class="project col-lg-6 col-md-6 col-sm-12 col-xs-12">|</div>
10 = TEXT
10 {
field = title
wrap = <h2>|</h2>
typolink.parameter.field = pages.uid
}
20 = CONTENT
20 {
table = tt_content
select {
pidInList.field = uid
selectFields = header, bodytext
orderBy = sorting ASC
}
renderObj = COA
renderObj {
30 = TEXT
30.value {
field = bodytext
wrap = <div>|</div>
}
}
}
}

TYPO3: Show content from a fixed page if there’s no content on current page

I would like to show content from a fixed page if there’s no content on current page.
An example: On the mainpage (pid=58) In the right col (colPos=31) I have a news plugin with the latest item. On subpages, it’s possible to insert content in the right col (colPos=31). It could be images,text etc. BUT, if the right col is empty I would like to show the news plugin from the mainpage as a fallback option.
This is my TypoScript, but it doesn’t work. Default content from mainpage are not showed, if there's no content from current page.
lib.rightCol-1 = COA
lib.rightCol-1 {
10 = COA
10 {
## Get content from current page.
10 = COA
10 < styles.content.get
## Get content from colPos 31
10.select.where = colPos=31
if.isTrue.current = 1
20 = CONTENT
20 {
## IF no content on current page show content from mainpage
stdWrap.if.isTrue.current = 1
stdWrap.if.negate = 1
table = tt_content
select {
## Get content from mainpage
pidInList = 58
where = colPos=31
orderBy = sorting
languageField = sys_language_uid
}
}
}
}
This can be done using stdWrap.override. If stdWrap.override returns something non-empty, this value replaces the normal value stdWrap would return. In your case, this could look like this:
# Fetch the default content from the mainpage with id 58
lib.rightCol-1 = CONTENT
lib.rightCol-1 {
table = tt_content
select {
pidInList = 58
where = colPos=31
orderBy = sorting
languageField = sys_language_uid
}
# override the content from page 58 with content from the current page,
# but only if there is content on this page
stdWrap.override.cObject = CONTENT
stdWrap.override.cObject {
table = tt_content
select {
pidInList = this
where = colPos=31
orderBy = sorting
languageField = sys_language_uid
}
}
}
You can also create the following behaviour:
If there is content on the current page, show it.
Else, walk up the rootline and take the content from the first page that has content in the column.
If there is no such page, take the content from the "mainpage".
This can be done by simply setting slide = -1 to the second CONTENT-Object.
Thanks for answer but I couldn't get it to work. Instead this worked:
lib.rightCol-1 = CONTENT
lib.rightCol-1 < styles.content.get
lib.rightCol-1.select.where = colPos=31
lib.rightCol-1 {
stdWrap.ifEmpty.cObject = CONTENT
stdWrap.ifEmpty.cObject {
table = tt_content
select {
pidInList = 58
orderBy = sorting
where = colPos = 31
languageField = sys_language_uid
}
}
}