Dynamicly change TYPO3 fluid Layout by typeNum - typo3

I am using the extension fluidpages and want to switch the layout by the typeNum.
is it possible to change the f:layout by by an condition?
This wont work:
<f:layout name="{f:if(condition: '{typeNum} == 666', then: 'PageAjax', else: 'Page')}"/>

Suggested approach:
<f:layout name="Page/{typeNum}"/>
Required files:
Resources/Private/Layouts/Page/0.html
Resources/Private/Layouts/Page/666.html
Please note: this only works if the {typeNum} variable is guaranteed to exist - if it does not, you will face a "template file not found" error with an empty filename. To avoid this, you can use the VHS extension's v:var.convert ViewHelper to ensure a proper value:
<f:layout name="Page/{typeNum -> v:var.convert(type: 'integer')}"/>

I got the same problem recently, and found the solution after a few researchings.
The problem is, you can not use nested fluid like <f:if>, <f:cObject> or others in <f:layout>. Otherwise, you will get a fatal error in the cache file, saying call to a member function getViewHelper() on a non-object. And when you look at the cache file, you will find it's because $self is not defined.
Therefore, my solution is, searching public function getLayoutName( in \TYPO3\CMS\Fluid\Core\Compiler\TemplateCompiler, and adding \$self = \$this; before \$currentVariableContainer = \$renderingContext->getTemplateVariableContainer();, just like generateCodeForSection()

I have now added the Condition in the Layout template. I get the typeNum from typoscript.
<f:if condition="{f:cObject(typoscriptObjectPath:'plugin.nc_template.settings.pageLayout')} == 'Default'">
<p>Default Template</p>
</f:if>
<f:if condition="{f:cObject(typoscriptObjectPath:'plugin.nc_template.settings.pageLayout')} == 'Ajax'">
<p>Ajax Template</p>
</f:if>
I found an example on the fedext Page, but could not get this to run:
https://fedext.net/blog/archive.html?tx_news_pi1[news]=55&tx_news_pi1[%40widget_0][currentPage]=8&cHash=f9c3165598a28d2aa98fd30ef115bb75

Can´t you use an if-statement instead?
IMHO this is easier to read - and if you need to add more arguments which depends on typeNum, it would stay readable.
<f:if condition="{typeNum} == 666">
<f:then>
<f:layout name="PageAjax">
</f:then>
<f:else>
<f:layout name="Page">
</f:else>
</f:if>

Related

fluid template: render image only if it exists

How can I use f:if to see if an image exists on the server before trying to render it?
I have tried the following without success:
<f:if condition="fileadmin/bilder/Header/{data.title}.jpg">
<f:then>
<f:variable name="imageUri" value="fileadmin/bilder/Header/{data.title}.jpg" />
</f:then>
<f:else>
<f:variable name="imageUri" value="fileadmin/bilder/Header/default.jpg" />
</f:else>
</f:if>
{data.title} works correkt. The Problem is that my condition is wrong. It never goes to the else. Probably my condition is interpret as a string und not as an source.
Description here doesn´t help because my Image is on the server.
Render image in fluid template if it exists?
First of all, why would you have a hardcoded path to a file in fileadmin in a template? That's very uncommon, most of the time you have some kind of relation through TYPO3 (e.g. through the media field in the pages table or something like that).
If this is still something you need, you'd have to write a FileExistsViewHelper that checks if the file exists before using it. Here's the documentation on how to write a custom view helper: https://docs.typo3.org/m/typo3/book-extbasefluid/master/en-us/8-Fluid/8-developing-a-custom-viewhelper.html
You'd need to register your filename as an argument with registerArgument and then prepend the path to the TYPO3 installation (to make it an absolute path) and check for this file with file_exists.
Extend from \TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper and implement the verdict method.
Your template above just creates a string (as you already guessed).

Controller action - redirect to another template

I am looking for a way to redirect to another template if certain conditions are fulfilled.
Like:
public funtion redirectAction() {
if(certain conditions = TRUE){
REDIRECT TO ANOTHER TEMPLATE WITH DIFFERENT CONTENT
}
}
I've seen some expressions in existing actions:
$this->redirect('list');
In this case, 'list' is the default List.html template, right?
So I thought if I replaced the 'list' with a different template name, that would solve the problem. But i get a opps error.
Or is there any other solution of calling a different template?
Thank you very much!
with a redirect in the controller you always redirect to another function, not a template.
For example with
$this->redirect('list2');
You would then redirect to the function list2Action() and this would expect a Template List2.html
Often however, it is easier to use a switch in fluid.
for example:
<f:if condition="{abc} == 1">
<f:then>
<f:render partial="TempalteAbcTrue" arguments="{_all}" />
</f:then>
<f:else>
<f:render partial="TempalteAbcFalse" arguments="{_all}" />
</f:else>
If you used the normal folder structure of extbase you have a "Layouts", "Templates" and "Partials" folder.
With the example above you can create 2 files in the folder "Partials": "TempalteAbcTrue.html" and "TempalteAbcFalse.html".

How to implement multilingual labels in tx:mask (TYPO3)?

I would like implement multilingual labels in TYPO3 mask. After implementing with the following FLUID-code the label does not change based on the chosen language:
<f:link.page pageUid="{data.tx_mask_inhalt_text_link}">
<f:if condition="{TSFE.sys_language_uid} == 1">
<f:then>
enter code here`Read more
</f:then>
<f:else>
Weiterlesen
</f:else>
</f:if>
</f:link.page>
I solved the issue with:
MASK-Template:
<f:translate key="label" />
TYPO3-Setup:
plugin.tx_mask._LOCAL_LANG.de.label = Weiterlesen
plugin.tx_mask._LOCAL_LANG.en.label = Read more
Works like a charm.
You can use XLIFF files to localize values in TYPO3. This is neither limited to nor different for mask templates (as these are common Fluid templates).
A locallang.xlf contains entries like:
<trans-unit id="readmore">
<source>Read more</source>
<target>weiterlesen</target>
</trans-unit>
In the HTML template you can use the f:translate viewhelper:
<f:translate key="LLL:EXT:your_extension/Resources/Private/Language/locallang.xlf:readmore" />
This will render the value depending on the current frontend language.
This is the usual way of translating in TYPO3. Please refer to these official documentations for all details:
XLIFF | TYPO3 documentation
f:translate | Fluid guide

In TYPO3 Fluid, how to pass additional arguments to a partial when {_all} is used

Fluid Styled Content uses the f:render Viewhelper as such:
<f:render partial="Header" arguments="{_all}" />
I'd like to pass another info to the partial, like
<f:render partial="Header" arguments="{_all, settings : doThis}" />
But it seems to me that's the wrong way, as it throws an error.
I also tried accessing settings.doThis with f:alias, but no luck (or rather, skill) either.
How's that done correctly?
This is possible with the alias ViewHelper. I already used it with TYPO3 version 6 and 7.
Just extend the {_all} var as following
Partial
<f:alias map="{additionalVar: 'foobar'}">
<f:render partial="Partial" arguments="{_all}"/>
</f:alias>
Section
<f:alias map="{additionalVar: 'foobar'}">
<f:render section="Section" arguments="{_all}" />
</f:alias>
You can use the "additionalVar" variable as any other.
It is working with section and partial.
You can't, so just modify your settings (or any other var) in the controller yet or use ViewHelper, which allows you to declare vars in the view, like i.e.: v:variable.set of VHS ext.
It is possible to use this one, but don´t use the var 'settings'. This one is used by typoscript.
<f:render partial="Header" arguments="{_all, myvar:'myvalue'}" />
Try the <f:debug> tag in the Header Partial and see
You can use vhs viewhelper with fluid like below.
<v:variable.set value="{yourValue}" name="variable">
<f:render partial="Header" arguments="{_all, newVar:variable}" />

How to make circle with break in fluid?

I want to stop my circle after output first element.
<f:for each="{errors}" as="error">
<f:switch expression="{error.code}">
<f:comment>The given subject was not a valid email address</f:comment>
<f:case value="1221559976">
<f:translate extensionName="helper" key="validator.emailaddress.notvalid" />
</f:case>
...
</f:switch>
BREAK????
</f:for>
Is it possible with fluid? Regards, Anton
You don't even need to iterate the collection, what for? Instead you can just fetch first element like: {errors.0}
Additionally if you want to fetch i.e. first 3 elements, you can prepare $limitedErrors (or smth) in your PHP controller and then assign it into the view.
It will be still more comfortable than manipulating within the template engine.
You can make you for each loop with additional argument iteration=""
add below code
<f:for each="{errors}" as="error" iteration="errorIterator">
and add condition
<f:if condition="{errorIterator.index} = 0">
or
<f:if condition="{errorIterator.isFirst}">
May you can use vhs viewhelper
<v:switch value="{variable}">
<v:case case="someValue" break="TRUE">
<!-- do whatever, if {variable} == 'someValue' -->
</v:case>
<v:case case="default">
<!-- the case "default" is a reserved keyword which acts as the default case. -->
</v:case>
</v:switch>
break > boolean