What I would like to achieve is that an image changes depending on what language is selected at that moment.
This is my HTML
<f:if condition="{TSFE:sys_language_uid} == 1">
<f:then>
<f:link.page pageUid="{settings.rootpid}" class="navbar-brand">
<img src="fileadmin/branding/brand/images/png/image1.png" alt="Logo {settings.brandname}" />
</f:link.page>
</f:then>
<f:else>
<f:link.page pageUid="{settings.rootpid}" class="navbar-brand">
<img src="fileadmin/branding/brand/images/png/image2.png" alt="Logo {settings.brandname}" />
</f:link.page>
</f:else>
</f:if>
And this is my TS
[globalVar = GP:L = 1]
config {
sys_language_uid = 1
language = nl
locale_all = nl_NL.UTF-8
htmlTag_setParams = lang="nl" dir="ltr" class="no-js"
}
[global]
[globalVar = GP:L = 2]
config {
sys_language_uid = 2
language = fr
locale_all = fr_FR.UTF-8
htmlTag_setParams = lang="fr" dir="ltr" class="no-js"
}
[global]
I tried a ton of different ways of writing this but can't seem to make it work hopefully somebody can help.
I assume that you are using your own distribution, or extend the functionality of some package ...
Try this in your constants.ts (so they are available in the BE constant editor) myext/Configuration/TypoScript/constants.ts :
myext.configuration {
logo {
src {
# cat=myext/general/05; type=string; label=English Logo
default = fileadmin/branding/brand/images/png/image0.png
# cat=myext/general/06; type=string; label=Dutch Logo
nl = fileadmin/branding/brand/images/png/image1.png
# cat=myext/general/07; type=string; label=French Logo
fr = fileadmin/branding/brand/images/png/image2.png
}
}
}
then this in your setup.ts myext/Configuration/TypoScript/setup.ts :
page = PAGE
page {
# Page Main template
10 = FLUIDTEMPLATE
10 {
variables {
# Logo
logoSrc = TEXT
logoSrc.value = {$myext.configuration.logo.src.default}
}
}
}
[globalVar = GP:L=1]
page.10.variables.logoSrc.value = {$myext.configuration.logo.src.nl}
[end]
[globalVar = GP:L=2]
page.10.variables.logoSrc.value = {$myext.configuration.logo.src.fr}
[end]
now you can simply use {logoSrc} in your fluidtemplate
...
<f:link.page pageUid="{settings.rootpid}" class="navbar-brand">
<img src="{logoSrc}" alt="Logo {settings.brandname}" />
</f:link.page>
...
Pass the pre-evaluated boolean to the template. Either from your controller (there you have access to the TSFE) or via TS to the FLUIDTEMPLATE object. It's not clear from the question where you are coming from. You should move the condition inline into the src, this way you don't duplicate the whole markup, but only switch the value.
Alternatively, you can pre-calculate the src value in the controller or TS and just pass it to the view.
You can get current languageUid using viewHelper something like below.
You ViewHelper file.
<?php
namespace MyVendor\ExtensionKey\ViewHelpers;
class GetLangUidViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
/**
* GetLangUid
*
**/
public function render() {
return $GLOBALS['TSFE']->sys_language_uid;
}
}
In your fluid template get current laguageUid like below.
{namespace L=MyVendor\ExtensionKey\ViewHelpers}
<f:if condition="{L:getLangUid()} == 1">
<f:then>
<f:link.page pageUid="{settings.rootpid}" class="navbar-brand">
<img src="fileadmin/branding/brand/images/png/image1.png" alt="Logo {settings.brandname}" />
</f:link.page>
</f:then>
<f:else>
<f:link.page pageUid="{settings.rootpid}" class="navbar-brand">
<img src="fileadmin/branding/brand/images/png/image2.png" alt="Logo {settings.brandname}" />
</f:link.page>
</f:else>
</f:if>
Related
I want to include a nav-item in my static menu from where i can change the site language.
Here is an example how to create DataProcessor and how to handle it in Fluid templates.
TypoScript:
page.10 = FLUIDTEMPLATE
page.10 {
layoutRootPath = EXT:your_sitepackage/Resources/Private/Layouts/Page/
partialRootPath = EXT:your_sitepackage/Resources/Private/Partials/Page/
file = EXT:your_sitepackage/Resources/Private/Templates/Page/Default.html
dataProcessing {
10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
10 {
entryLevel = 0
levels = 2
expandAll = 1
as = mainNav
}
20 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
20 {
special = directory
# This number is the sysfolder holding the header navigation pages
special.value = 11
as = headerNav
}
30 = TYPO3\CMS\Frontend\DataProcessing\LanguageMenuProcessor
30 {
languages = auto
as = languageNav
}
40 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
40 {
special = directory
# This number is the sysfolder holding the footer navigation pages
special.value = 13
as = footerNav
}
}
}
In Fluid you get an array with all pages fetched by the different DataProcessors:
<f:if condition="{mainNav}">
<ul class="nav-main">
<f:for each="{mainNav}" as="item">
<li class="nav-main__item{f:if(condition: '{item.active}', then: ' nav-main__item-active')}">
<a href="{item.link}">
{item.title}
</a>
</li>
</f:for>
</ul>
</f:if>
Or the language menu:
<f:for each="{languageNav}" as="item">
<li class="language__item">
<f:if condition="{item.active}">
<f:then>
<span>{item.navigationTitle}</span>
</f:then>
<f:else>
{item.navigationTitle}
</f:else>
</f:if>
</li>
</f:for>
Of course you can choose your own classes and structure, but this possibility gives you a much easier integration.
Hope, it helps
How can I deliver prepared fluid form elements using PHP and have them process in a fluid template?
Something like:
Controller:
public function indexAction(): void {
$html = '<div class="wrap">
<f:form.textfield name="email" value=""/>
<f:form.textfield name="token" value="a#b.com"/>
</div>';
$this->view->assign('elements', ['data' => $html]);
}
Index Template:
<f:form ...">
<div class="F">{elements.data -> f:format.raw()}</div>
</f:form>
Rendering Fluid is no iterating process and so your Fluid in a variable will not be rendered as Fluid.
If you want variants you could use partials which can be controlled by a variable
<f:if condition="{var1} == 'long'">
<f:then>
<render partial="longVersion" arguments="{_all}" />
</f:then>
<f:else>
<render partial="shortVersion" arguments="{_all}" />
</f:else>
</f:if>
you even can use the variabel to select the partial directly:
<f:render partial="Part_{var1}" arguments="{_all}" />
Another way would be to insert the rendered Fluid in to the variable.
in Typoscript this coul be like this:
10 = FLUIDTEMPLATE
10 {
template = outer
variables {
part1 = FLUIDTEMPLATE
part1 {
template = inner
variables {
:
}
}
:
}
}
or dynamically:
<f:cObject typoscriptObjectPath="lib.subtemplate">
lib.subtemplate = FLUIDTEMPLATE
lib.subtemplate {
template = inner
variables {
:
}
}
Page's Resources Tab
I have been trying to access these files but with no luck. Any help is appreciated.
If your system has EXT:vhs installed you can get this via vhs viewhelper like this,
{namespace v=FluidTYPO3\Vhs\ViewHelpers}
<v:page.resources.fal table="pages" field="media" uid="{page.uid}" as="images" slide="-1" >
<f:for each="{images}" as="image">
<f:image src="{image.url}" alt="{image.alternative} {image.name}" title="{image.title}" />
</f:for>
</v:page.resources.fal>
you can get more about this from here: https://github.com/FluidTYPO3/vhs/pull/395 and https://fluidtypo3.org/viewhelpers/vhs/2.3.3/Page/Resources/FalViewHelper.html#argument-slide
You can use typoscrpt solution as well,
lib.pageResources = FILES
lib.pageResources {
references {
table = pages
uid.data = uid
fieldName = media
}
renderObj = IMAGE
renderObj {
file {
import.data = file:current:uid
treatIdAsReference = 1
width = 150c
height = 150c
}
altText.data = file:current:alternative
titleText.data = file:current:title
}
maxItems = 3
}
Render this with:
<f:cObject typoscriptObjectPath="lib.pageResources" />
You can get more about this from here: https://riptutorial.com/typo3/example/21734/image-and-image-resource
Hope this helps you... #KeepCoding.. ;)
Regards
To access the Page Resources files / image in the TYPO3 Fluid, take this example:
<f:if condition="{files}">
<f:then>
<f:for each="{files}" as="image">
<f:uri.image image="{image}" />
</f:for>
</f:then>
</f:if>
all the Page Resources files / images find you in the "files". take the <f:debug>{_all}</f:debug>
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>
I have a typo3 fluid template in which I want to check if content exists before rendering some elements.
Is there an efficient way to do this?
eg.
<f:if condition="{contentInColPos0}">
<div class="section-content">
<f:render section="Main" />
</div>
</f:if>
Is there a built-in variable or a simple way to check content exists in a column position?
This is a common task in CMS templating (don't render this part unless there's something to show), but I can't seem to find how to do it simply.
There is no easy way to do that. But you can use some TypoScript and then pass the count to Fluid and use it in a condition:
lib.countContent = CONTENT
lib.countContent {
table = tt_content
select {
selectFields = count(uid) AS count
pidInList = this
andWhere = (deleted = 0 AND hidden = 0)
}
renderObj = COA
renderObj {
10 = TEXT
10 {
data = field:count
}
}
This object will output the number of content rows on the given page and can be accessed in Fluid:
<f:if condition="{f:cObject(typoscriptObjectPath:'lib.countContent')} > 0">
Then show some stuff
</f:if>
If you're going to use the content anyway and don't have global wrap in your content object, you can also use it directly because the Fluid IfViewHelper checks for empty strings. So e.g. this might be working even better:
lib.content < styles.content.get
(This object is empty if there is no content)
<f:if condition="{f:cObject(typoscriptObjectPath:'lib.content')}">
<f:then>
<f:format.html>{lib.content}</f:format.html>
</f:then>
<f:else>
No content found
</f:else>
</f:if>
Easyest way to check this with VHS and without TypoScript:
<f:if condition="{v:content.get(column:6) -> v:iterator.first()}">
<div class="myAmazingClass">
</div>
</f:if>
You can slide the content throug subpages if you want:
<f:if condition="{v:content.get(column:6, slide:'-1') -> v:iterator.first()}">
<div class="myAmazingClass">
</div>
</f:if>
Consider VHS with ViewHelpers https://fluidtypo3.org/viewhelpers/vhs/master/Content/GetViewHelper.html or https://fluidtypo3.org/viewhelpers/vhs/master/Content/RenderViewHelper.html combined with using the as argument and an f:if condition to check the assigned variable for being empty.
You can solve this easily:
In your TypoScript file:
lib.contentInColPos0 < styles.content.get
lib.contentInColPos0 t.select.where = colPos = 0
In your Template file:
<f:if condition="{f:cObject(typoscriptObjectPath:'lib.contentInColPos0')}">
<div class="section-content">
<f:render section="Main" />
</div>
</f:if>