I am using the typoscript below to display news content via a CONTENT object. Everything is working great except the link doesn't go to the page of the article. Is there a way to tell the typolink that this is a news article and that it should use the cached CoolURI link for it?
Also, the additionalParameter I'm trying to append to the querystring isn't appearing.
temp.MMtest = COA
temp.MMtest {
10 = CONTENT
10.table = tt_news
#10.select.pidInList = 170 # Uid of the sysfolder where News records are stored
10.select.pidInList = 18
10.select.recursive = 10
#10.select.where = uid=10 # Uid of an existing News record
10.select.andWhere = deleted=0 AND hidden=0
10.renderObj = COA
10.renderObj {
10 = TEXT
10.field = title
10.wrap = Title: |<br>
10.typolink.parameter.field=uid
typolink.parameter.dataWrap=|
#typolink.additionalParams.insertData=1
typolink.additionalParams.data=&my_extra_param=something
#if.isTrue.field=header
}
10.renderObj.20=IMAGE
10.renderObj.20{
wrap=|
# show it only if inserted
stdWrap.if.isTrue.field=image
stdWrap.typolink.parameter.field=uid
file.import=uploads/pics/
file.import.field=image
file.width=100
file.height=100
}
}
I do not know, which parameters you need, so in short:
10.typolink {
# you need a page to link too
parameter = PAGE_ID_OF_SINGLE_VIEW
# create an cacheable link, that does not depend on cooluri or realurl.
useCacheHash = 1
# add the additional params
additionalParams.wrap = &tx_ttnews[uid]=|
# data expects special commands
# "&my_extra_param=something" cannot work on .data
additionalParams.data = field:uid
}
If you need more then one additionalParams i would do it this way:
10.typolink {
parameter = PAGE_ID_OF_SINGLE_VIEW
useCacheHash = 1
# Create an Content Object Array
# so you can separat the different entries
# the cObject will return &tx_ttnews[uid]=123&what[ever]=hardcodedvalue
# additionalParams is filled with that string and added to the url
additionalParams.cObject = COA
additionalParams.cObject {
10 = TEXT
10.wrap = &tx_ttnews[uid]=|
10.field = uid
20 = TEXT
20.wrap = &what[ever]=|
20.value = hardcodedvalue
}
}
You do not need
10.select.andWhere = deleted=0 AND hidden=0
this is added automatically by the CONTENT Object.
Read more about typolink about COA and about stdWrap and its property data and finally have a look at getText.
Related
I have a menu (HMENU with special = updated) that gives me the latest sub and sub-sub pages from 3 categories.
The page structure looks like this in the backend:
In addition to the title, I would like to output the name of the respective category (the parent level-1 page).
This is my TypoScript attempt:
lib.myMenu = HMENU
lib.myMenu {
special = updated
special{
value.field = 10,11,12
beginAtLevel = 1
limit = 99
}
1 = TMENU
1{
NO{
doNotLinkIt = 1
stdWrap.cObject = COA
stdWrap.cObject {
10 = TEXT
10{
wrap = <h3>|</h3>
field = seo_title // title
typolink.parameter.field = uid
}
20 = HMENU
20{
wrap = <div class="category attempt-1">|</div>
special = rootline
special.range = 1|1
special.value.field = uid # does not work
1 = TMENU
1.NO.allWrap = |
}
30 = TEXT
30{
wrap = <div class="category attempt-2">|</div>
data = leveltitle : 1 # does not work as expected
}
}
}
}
}
Unfortunately it does not work, because …
special = rootline does not support special.value.
data = leveltitle : 1 uses the ID of the current page, instead of the TMENU item ID.
Does anyone have another approach how I can get the title of the respective category using TypoScript?
Edit: Background information / what this is needed for
With this menu I intend to replace the news module ext:news of an existing project. Instead of news records, pages are now used and this menu creates the list view. Of course a TypoScript page browser will be added.
I would not rebuild the complete menu item generation (NO.doNotLinkIt = 1).
Just use NO.after.cObject = COA.
leveltitle : 1 is correct if you want to have the title for the current page.
The same if you show a rootline menu: it is generated for the current page.
If you want the levelfield for another page you need to build it by yourself.
In typoscript you might use a userfunction. (there is a core function for getting the rootline for a given page id)
If you generate your menu with FLUID you might use a viewhelper. (You might get inspired from this option of viewhelper menu.directory or this option of VH page.breadCrumb in ext:vhs.)
Edit:
you might store the needed information directly in the pagesrecord.
add a new field to the record (or use any unused).
then make sure that each category page contains some page TS_config:
TCADefaults.pages.<yourfield> = CategoryName
With this configuration each new page below will get this value set automatically.
Of course you need to set these values for all existing pages by hand or by some manual queries.
And if the editors are to be prevented from changing this value you need to remove the field from the edit form with this TSConfig on the top-page:
TCEForm.pages.<yourfield>.hide= 1
I have found a pure TypoScript solution that may not be very elegant, but it works:
lib.myMenu = HMENU
lib.myMenu {
special = updated
special{
value.field = 10,11,12
beginAtLevel = 1
limit = 99
}
1 = TMENU
1{
NO{
doNotLinkIt = 1
stdWrap.cObject = COA
stdWrap.cObject {
10 = TEXT
10{
wrap = <h3>|</h3>
field = seo_title // title
typolink.parameter.field = uid
}
20 = HMENU
20{
wrap = <div class="category">|</div>
special = list
special.value.field = pid
1 = TMENU
1{
NO{
doNotLinkIt = 1
stdWrap.override{
# Overwrite it if we are not yet at the category level
if{
# The ID of the page parent to the categories ("Website") is 1618
equals = 1618
value.field = pid
negate = 1
}
cObject = HMENU
cObject{
special = list
special.value.field = pid
1 = TMENU
1.NO.doNotLinkIt = 1
}
}
}
}
}
}
}
}
}
If the menu is to go over further levels, the override must of course be nested even deeper.
Edit – Improvements:
RECORDS instead of HMENU: Bernd Wilke suggested in the comments to use CONTENT instead of HMENU to generate the category title. This caused problems in my tests when sysfolders (as subpages of the categories) were used to structure the items. This could be related to the bug/feature #20933 (Enable working with SysFolders in CONTENT). But RECORDS might be comparable. I tried it and was able to improve the render times a little bit (see table below).
lib.myMenu.1.NO.stdWrap.cObject.20 = RECORDS
lib.myMenu.1.NO.stdWrap.cObject.20{
stdWrap.wrap = <div class="category">|</div>
source.field = pid
tables = pages
conf.pages = TEXT
conf.pages {
field = seo_title // title
stdWrap.override{
# Overwrite it if we are not yet at the category level
if{
# The ID of the page parent to the categories ("Website") is 1618
equals = 1618
value.field = pid
negate = 1
}
cObject = RECORDS
cObject{
source.field = pid
tables = pages
conf.pages = TEXT
conf.pages.field = seo_title // title
}
}
}
}
CONTENT instead of HMENU: if no sysfolders are needed (as of TYPO3 10.4 sysfolders should also work)
lib.myMenu.1.NO.stdWrap.cObject.20 = CONTENT
lib.myMenu.1.NO.stdWrap.cObject.20{
stdWrap.wrap = <div class="category">|</div>
table = pages
select {
uidInList.field = pid
pidInList = 0
selectFields = uid, pid, seo_title, title
}
renderObj = TEXT
renderObj {
field = seo_title // title
stdWrap.override{
# Overwrite it if we are not yet at the category level
if{
# The ID of the page parent to the categories ("Website") is 1618
equals = 1618
value.field = pid
negate = 1
}
cObject = CONTENT
cObject{
table = pages
select {
uidInList.field = pid
pidInList = 0
selectFields = uid, pid, seo_title, title
}
renderObj = TEXT
renderObj.field = seo_title // title
}
}
}
}
userFunc instead of HMENU: Bernd Wilke suggested in his answer to use a userfunction. Even if this is not a pure TypoScript solution, I would have liked to test it to be able to compare the performance. The method getRootLine() has unfortunately been marked as deprecated. Since I'm not an extension developer, it's not clear to me yet how to read the category via a userFunc and if this is actually more effective. If I still come across a solution regarding this, it will be added here.
Rendertime: I have test-implemented the menu in the live site (in the existing template) and compared the website render times with and without the output of the categories to see how much the nested menu affects the performance. The values are average values from 10 measurements. I also limited the output to 20 items, which should be a more realistic value per page later on:
mode
20 items
100 items
without category
99 ms
218 ms
categories via HMENU
133 ms
353 ms
categories via RECORDS
132 ms
331 ms
categories via CONTENT
121 ms
255 ms
categories via userFunc
TBD
TBD
You should neither use a separate HMENU nor a userFunc but a simple LOAD_REGISTER within the menu items of the parent level. This generates register entries, that can be added, changed or restored while looping through the different levels of the HMENU structure.
So you don't need the custom code of a PHP function and you won't get the performance penalty of a nested HMENU.
Basically it's shown in the official documentation, but with a CSS class instead of a title. But of course you could hand over other information from the parent to its children the same way.
Here is the example:
10 = COA
10 {
### left menu table column
10 = LOAD_REGISTER
10 {
ulClass = col-left
}
### right menu table column
20 = LOAD_REGISTER
20 {
ulClass = col-right
}
30 = HMENU
30 {
special = list
special.value = 1
1 = TMENU
# ...
3 = TMENU
3 {
stdWrap {
preCObject = COA
preCObject {
10 = RESTORE_REGISTER
}
dataWrap = <ul class="{register:ulClass}">|</ul>
}
wrap =
SPC = 1
SPC {
allStdWrap {
replacement {
10 {
search = ---
replace =
}
}
dataWrap = </ul>|<ul class="{register:ulClass}">
}
}
}
}
}
And here the link to the full documentation page:
https://docs.typo3.org/m/typo3/reference-typoscript/master/en-us/UsingSetting/Register.html
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.
I need to get the page.headerData in typoscript from pi_flexform.How can implement my requirement?
page = PAGE
page {
headerData {
10 = TEXT
10.value =<script>/**********************/</script>
}
}
I am not so sure about what you really need. I am guessing you want to access a FlexForm configuration inside your TypoScript?
Since the version 8.4 this is possible by using plain TypoScript
lib.flexformContent = CONTENT
lib.flexformContent {
table = tt_content
select {
pidInList = this
}
renderObj = COA
renderObj {
10 = TEXT
10 {
data = flexform: pi_flexform:settings.categories
}
}
}
The key flexform is followed by the field which holds the flexform data and the name of the property whose content should be retrieved.
Before 8.4 you need to use a userFunc and retrieve the value by using PHP
$flexFormService = GeneralUtility::makeInstance(FlexFormService::class);
$flexFormKey = str_replace('.', '|', $keyParts[1]);
$settings = $flexFormService->convertFlexFormContentToArray($flexFormContent);
I'm using typoscript go get the first file out of a page. This works and is out of the documentation. But the documentation doesn't tell something about a fallback if no files are found.
lib.files = FILES
lib.files {
references {
table = pages
fieldName = media
}
file =
begin = 0
maxItems = 1
renderObj = TEXT
renderObj {
value = URL: {file:current:publicUrl}
insertData = 1
}
}
A naive .if.isNull failed at the first attpent. Is there a possibilty to define a fallback if the FILES-Object is empty?
Mh,
try to make a second object and check there if lib.files is filled with data.
__
UNTESTED
lib.files = FILES
lib.files {
references {
table = pages
fieldName = media
}
file =
begin = 0
maxItems = 1
renderObj = TEXT
renderObj {
value = URL: {file:current:publicUrl}
insertData = 1
}
}
lib.fileFallback = COA
lib.fileFallback {
10 < lib.files
20 = TEXT
20 {
value = Do something
stdWrap.if.isFalse.cObject < lib.fileFallback.10
}
}
I am using this technique often to slide through pages for slideshow objects.
Let me know, if it is working.
You should check the TypoScript Reference stdWrap.ifEmpty.
In your case the code should look like this
lib.files {
# ....
stdWrap.ifEmpty.cObject = IMAGE
stdWrap.ifEmpty.cObject{
file = fileadmin/.../my_image.png
}
# ....
}
You can use every cObject you want.
Check out Content Objects (cObject)
i want to add the language id in a typolink
so far
LOGO = COA
LOGO {
10 = TEXT
10 {
value = logo
typolink {
parameter = 116
additionalParams = &L={$config.sys_language_uid}
}
}
}
if L=4 it's working
but if i use L={$config.sys_language_uid} it gets ignored altogether
same with L=GP:L
and L=GPvar:L
what would be the proper syntax here
working if i do something like
additionalParams = COA
additionalParams {
10 = TEXT
10.data = GP : L
10.intval = 1
10.wrap = &L=|
}
You do not need to do that on your own. With the following global TypoScript configuration the parameter L will added to every link:
config.linkVars = L(int)
So, if you use HMENU.special = language this will be managed on the switch automatically, too:)
http://docs.typo3.org/typo3cms/TyposcriptReference/Setup/Config/Index.html
I do not know about {$config.sys_language_uid}, but your code will output it as plain text. In order to use variables like {GP:L}, you got to dataWrap it or insert "insertData" after the value.
10 = TEXT
10 {
value = logo
typolink {
parameter = 116
additionalParams.dataWrap = &L={GP:L}
}
}
OR (the best way I'd say):
10 = TEXT
10 {
value = logo
typolink {
parameter = 116
additionalParams.cObject = TEXT
additionalParams.cObject {
wrap = &L=|
data = GP:L
}
}
}
Using {TSFE:sys_language_uid} might be a better option if you are querying the database.
There is no need to make a cObject or COA
additionalParams = type=0&L={GP:L}
additionalParams.insertData = 1
You can do this kind of URL using addQueryString = 1. https://docs.typo3.org/typo3cms/TyposcriptReference/Functions/Typolink/Index.html#addquerystring