TypoScript: conditional wrap if more than one item - typo3

hmm... my TypoScript skills seem to have become a bit rusty.
lib.feld < styles.content.get
lib.feld.select.orderBy = rand()
lib.feld.select.select.where = colPos=11
lib.feld.wrap = <div class="wrapper">|</div>
I would like to add the wrapper div only if styles.content.get returns more than one item for said colPos.
I've tried the following two variants:
lib.feld.wrap.if {
isGreaterThan.numRows < styles.content.get
isGreaterThan.numRows.select.where = colPos=11
value = 1
}
and
lib.feld.wrap.if {
isGreaterThan.numRows.table = tt_content
isGreaterThan.numRows.select < styles.content.get.select
isGreaterThan.numRows.select.where = colPos=11
value = 1
}
also with an additional stdWrap before numRows.
Everything returns false, even when there should be multiple results.
What is wrong?

from typoscript definition I would guess:
temp.feld < styles.content.get
temp.feld.select.where = colPos=11
temp.feld.select.orderBy = rand()
temp.feld.select.pidInList = 123
lib.feld < temp.feld
lib.feld.wrap = <div>|</div>
lib.feld.wrap.if {
isGreaterThan.stdWrap.numRows < temp.feld
value = 1
}
for inspecting/debuggung the value of numRows you might use this:
lib.numRows = TEXT
lib.numRows.numRows < temp.feld
lib.numRows.wrap = numRows=[|]
which you can use in fluid
{f:cObject(typoscriptObjectPath:'lib.numRows')}
or in typoscript itself for output
page.3 < lib.numRows

Related

Typo3 inherit data when if is true

I generate an lib.content with the current content but i want to add it only if the following if statement will be true, otherwise not/empty:
lib.content = COA
lib.content{
10 < styles.content.get
10.stdWrap.cObject.if{
value.data = DB:pages:{page:uid}:nav_hide
value.data.insertData = 1
equals = 1
}
}
is this possible or where's the error in the syntax?
Version of Typo3 is 10.4
You need to use "insertData" twice, because it replaces {page:uid} with the UID (e.g. 5), but it keeps the rest DB:pages:5:nav_hide.
The rest DB:pages:5:nav_hide needs to be "data inserted" again, so the trick is to use wrap3.
Solution:
lib.content = COA
lib.content {
10 < styles.content.get
10.stdWrap.cObject.if {
// Replaces page:uid
value.dataWrap = DB:pages:{page:uid}:nav_hide
// Wraps curly brackets around DB:pages:5:nav_hide
value.wrap3 = {|}
// Replaces DB:pages:5:nav_hide with the nav_hide value
value.insertData = 1
equals = 1
}
}

Pass a variable to a content object containing a tx_news plugin

This is very similar to my question Counter for mask elements in a TYPO3 column
I need to pass a variable (in my case, the value of cObj:parentRecordNumber which is the counter for the current item in it's column) to the template.
In the main page template:
<f:cObject typoscriptObjectPath="lib.content.pageteasers" />
In typoscript:
lib.content {
pageteasers < styles.content.get
pageteasers {
select {
where = colPos=2
max = 8
}
// this passes the variable elementCounter to the fluid template of the rendered mask content element:
renderObj.mask_teaser {
variables {
elementCounter = TEXT
elementCounter.value = {cObj:parentRecordNumber}
elementCounter.insertData = 1
}
}
// this should pass the same value to a rendered tx_news plugin:
variables {
elementCounter = TEXT
elementCounter.value = {cObj:parentRecordNumber}
elementCounter.insertData = 1
}
// it doesn't. what about these trial & error:
renderObj.list < .variables
renderObj.plugin.tx_news < .variables
renderObj.list.20.news_pi1 < .variables
renderObj.news_pi1 < .variables
// none of these seem to work either
}
}
And then in the rendered CE template (News/List.html)
<f:debug title="" inline="1">{_all}</f:debug>
I don't manage to see the above variable in here. What is the correct way to pass the variable from TS to the news fluid template?
PS Another try was using the Good Old Register
pageteasers < styles.content.get
pageteasers {
select {
where = colPos=2
max = 8
}
append = LOAD_REGISTER
append {
elementCounter = TEXT
elementCounter.value = {cObj:parentRecordNumber}
elementCounter.insertData = 1
}
}
And in the template:
{v:variable.register.get(name: 'elementCounter')}
but that is NULL
Your try via register could work. But you have to care, where you are doing what...
Registers
LOAD_REGISTER is of type string/stdWrap and not a cObject per definition. If you wanna use content based on a cObject, you can declare this via the stdWrap-property (as shown in the examples):
1 = LOAD_REGISTER
1.param.cObject = TEXT
1.param.cObject.stdWrap.data = GP:the_id
So, in your case it should like:
elementCounter.cObject = TEXT
elementCounter.cObject.data = cObj:parentRecordNumber
Appending at the right place
You are trying to use append directly as a property of pageteasers (which is a copy of styles.content.get which is of type CONTENT.
CONTENT does not have an append-property. In addition, you would put the register in front of the entire content, not the individual content elements.
=> It's needed as part of the renderObj, so it's rendered per CE.
The renderObj of CONTENT is of type CASE, which also has no stdWrap-properties directly. But it has a property stdWrap with stdWrap-properties...
Conclusion
So, you can end up with this snippet:
lib.content {
pageteasers {
renderObj {
stdWrap {
append = LOAD_REGISTER
append {
elementCounter.cObject = TEXT
elementCounter.cObject.data = cObj:parentRecordNumber
}
}
}
}
}

TYPO3 - simpler way, rendering content from colPos into Fluidtemplate?

The official TYPO3 Documentation explains how to create (or copy) and use a lib.dynamicContent to render columns into a Fluidtemplate.
I do not understand exactly whats going on in this example.
The TypoScript there is:
lib.dynamicContent = COA
lib.dynamicContent {
10 = LOAD_REGISTER
10.colPos.cObject = TEXT
10.colPos.cObject {
field = colPos
ifEmpty.cObject = TEXT
ifEmpty.cObject {
value.current = 1
ifEmpty = 0
}
}
20 = CONTENT
20 {
table = tt_content
select {
orderBy = sorting
where = colPos={register:colPos}
where.insertData = 1
}
}
90 = RESTORE_REGISTER
}
I use this snippet in a ton of TYPO3 projects and often had asked myself whats going on there.
I have changed this by experimenting a bit and ended with:
lib {
dynamicContent = COA
dynamicContent {
10 = CONTENT
10 {
table = tt_content
select {
orderBy = sorting
where {
data = field:colPos
wrap = colPos=|
}
}
}
}
}
That seems to do "exactly the same" thing - it outputs my content when called via cObject ViewHelper.
Can somebody explain if or why this is the worse way to render Content?
Here's the link to the lib.dynamicContent-doc: https://docs.typo3.org/c/typo3/cms-fluid-styled-content/master/en-us/Installation/InsertingContentPageTemplate/Index.html#based-on-the-fluidtemplate-content-object-cobj
Here you go!
you can try this,
# Clear out any constants in this reserved room!
styles.content >
# get content
styles.content.get = CONTENT
styles.content.get {
table = tt_content
select.orderBy = sorting
select.where = colPos=0
}
# Left Column
styles.content.getLeft < styles.content.get
styles.content.getLeft.select.where = colPos=1
# Right content
styles.content.getRight < styles.content.get
styles.content.getRight.select.where = colPos=2
Also, you can use variable in the fluid page object, check this out:
lib.pageTemplate = FLUIDTEMPLATE
lib.pageTemplate {
variables {
content = CONTENT
content {
table = tt_content
select.orderBy = sorting
select.where = colPos=0
}
contentRight = CONTENT
contentRight {
table = tt_content
slide = -1
select.orderBy = sorting
select.where = colPos=2
}
}
}
You can find out more here:
Adding the page content to a fluid template
Typo3 7.6 typoscript problems with markers
Hope this make sense, Cheer...!
You should look at this snippet together with some information about the Fluid view helper <f:cObject> which can be found here: https://docs.typo3.org/other/typo3/view-helper-reference/9.5/en-us/typo3/fluid/latest/CObject.html
As you can see there are the parameters data, currentValueKey and table that will be handed over to the typoscriptObjectPath, which is why the snippet makes perfect sense. The reason is, that it's a bit hard to put the different options into the where clause of the CONTENT object. So it increases readability and those registers can be easily extended.
So the register in this example is used to put in either the value of the data field colPos or if that is empty it will take the current value from the currentValueKey and if that is empty too it will fall back to a value of 0 to make sure the query won't produce an exception.
lib.dynamicContent = COA
lib.dynamicContent {
10 = LOAD_REGISTER
10.colPos.cObject = TEXT
10.colPos.cObject {
field = colPos
ifEmpty.cObject = TEXT
ifEmpty.cObject {
value.current = 1
ifEmpty = 0
}
}
20 = CONTENT
20 {
table = tt_content
select {
orderBy = sorting
where = colPos={register:colPos}
where.insertData = 1
}
}
90 = RESTORE_REGISTER
}
We used a modified version of that snippet to sneak in some more parameter values for the CONTENT object.
So we can hand over a data field pageUid, if that is not set we will use the uid of the current page. This will be overriden if the current or the target page is configured to show content from another page and finally we can trigger a slide with another data field.
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
}
}
20 = CONTENT
20 {
table = tt_content
slide = -1
slide.if.isTrue.field = slide
select {
includeRecordsWithoutDefaultTranslation = 1
orderBy = sorting
where = {#colPos}={register:colPos}
where.insertData = 1
pidInList.data = register:pageUid
pidInList.override.data = register:contentFromPid
}
}
90 = RESTORE_REGISTER
}
This enables us to make use of the <f:cObject> view helper while triggering additional parameters just by handing over some more values within the data array.

TYPO3 fluid variables

I upgrade my TYPO3 from 7.6 to 8.6.
Now I cant set variables via style.content.get, my root template loads fluid_styled_content.
some source:
page.10 = FLUIDTEMPLATE
page.10 {
partialRootPath ={$resDir}/Private/Partials
layoutRootPath = {$resDir}/Private/Layouts
variables {
contentMain < styles.content.get
contentMain.select.where = colPos = 0
contentnew < styles.content.get
contentnew.select.where = colPos = 1
contentkat < styles.content.get
contentkat.select.where = colPos = 2
test = TEXT
test.value = loool
}
}
display the variables:
<f:format.raw> {contentMain} </f:format.raw>
<f:format.raw> {contentnew} </f:format.raw>
<f:format.raw> {contentkat} </f:format.raw>
<f:format.raw> {test} </f:format.raw>
styles.content.get is defined in ext:fluid_styled_content but very late so most copies are empty. References are no solution as the modification for colPos would apply to all references.
At the moment the best solution seems to be an own definition of styles.content.get early in your TS:
styles.content.get = CONTENT
styles.content.get {
table = tt_content
select {
orderBy = sorting
where = colPos=0
}
}
but as it is an own definition I would rename it to temp.content.get so it is identifiable as my own version (no confusion if the global definition changes)
There is a Bug in TYPO3 8.6: https://forge.typo3.org/issues/80044
Add this before you assign styles.content.get to your variables:
<INCLUDE_TYPOSCRIPT: source="FILE:EXT:frontend/ext_typoscript_setup.txt">
Then you can use it just as before.
SOLVED
Thanks to Bernd! Solved this problem.
Here a full example:
mystyles.content.get = CONTENT
mystyles.content.get {
table = tt_content
select {
orderBy = sorting
where = colPos=0
}
}
page.10 = FLUIDTEMPLATE
page.10 {
partialRootPath ={$resDir}/Private/Partials
layoutRootPath = {$resDir}/Private/Layouts
variables {
contentMain < mystyles.content.get
contentMain.select.where = colPos = 0
contentnew < mystyles.content.get
contentnew.select.where = colPos = 1
contentkat < mystyles.content.get
contentkat.select.where = colPos = 2
test = TEXT
test.value = loool
}
}

typo3 css_styled content edit source

I have the following problem:
I am using typo3 4.7.7 and I am adding custom columns in the Backend. I am able to do taht by place a configuration array in the /typo3conf/extTables.php
$TCA["tt_content"]["columns"]["colPos"]["config"]["items"] = array (
"3" => array ("Border,"3"),
"2" => array ("Right","2"),
"1" => array ("Left","1"),
"0" => array ("Normal","0"),
"5" => array ("Central","5"),
"6" => array ("Border","6"),
"4" => array ("Footer","4")
);
Then set:
mod.SHARED.colPos_list=0,1,2,3,4,5,6
in the TSconfig.
It is working, I enjoy my new columns :), but there is a problem. I want to be able to use the css_styled_content to map my new columns to my html template. This is not possible, because the "get" constants of css_styled_content are hard coded and I am not able to use something like "content.getFooter". At the moment the only way I can get my content is like this:
...
page.10 = CONTENT
page.10.table = tt_content
page.10.select {
orderBy = sorting
where = colPos = 4
}
page.10.renderObj = COA
page.10.renderObj {
10 = TEXT
10.field = header
20 = TEXT
20.field = bodytext
}
...
This is a lot of code, so I was wondering if there is a way to "make" CSC recognize my new columns, so that I would be able to use "content.getMYCUSTOM_COLUMN_NAME".
P.S. I do not want to use templavoila and I found something in the source of CSC under /static/setup.txt :
# Clear out any constants in this reserved room!
styles.content >
# get content
styles.content.get = CONTENT
styles.content.get {
table = tt_content
select.orderBy = sorting
select.where = colPos=0
select.languageField = sys_language_uid
}
# get content, left
styles.content.getLeft < styles.content.get
styles.content.getLeft.select.where = colPos=1
# get content, right
styles.content.getRight < styles.content.get
styles.content.getRight.select.where = colPos=2
# get content, margin
styles.content.getBorder < styles.content.get
styles.content.getBorder.select.where = colPos=3
# get news
styles.content.getNews < styles.content.get
styles.content.getNews.select.pidInList = {$styles.content.getNews.newsPid}
# Edit page object:
styles.content.editPanelPage = COA
styles.content.editPanelPage {
10 = EDITPANEL
10 {
allow = toolbar,move,hide
label.data = LLL:EXT:css_styled_content/pi1/locallang.xml:eIcon.page
label.wrap = | <b>%s</b>
}
}
I then tried to add:
# get content, footer
styles.content.getFooter < styles.content.get
styles.content.getFooter.select.where = colPos=4
But it did not work.
you are on the right track. try to create your own Content Object:
temp.footer < styles.content.get
temp.footer.select.where = colPos=4
page = PAGE
page.100 < temp.footer