Add category uid to news detail - typo3

I setup a TYPO3 website with News System Ext. and I need to add the category ID to the entry class on the file : fileadmin\templates\ext\news\Templates\News\Detail.html
so, the final output will be as follows
<div class="entrys category-uid-[id here]"></div>

There is a little difference if you want just the first category or all categories.
<f:section name="firstCatClass">
<f:for each="categories" as="category" iteration="iterator"><f:if condition="{iterator.isFirst}"> category-uid-{category.uid}</f:if></f:for>
</f:section>
<f:section name="allCatClasses">
<f:for each="categories" as="category"> category-uid-{category.uid}</f:for>
</f:section>
then you can insert this in the class-parameter of your divtag.
<div class="entrys{f:render(section:'allCatClasses', arguments:'{categories:item.categories}')}">
for only the first category there already is a handling in the partial List/Item.html which you can modify to:
<div class="entrys{f:if(condition:newsItem.firstCategory, then:' category-uid-{newsItem.firstCategory}')}">

Related

TYPO3 Fluid: How to pass several domain objects to the action controller

I want to have a big Fluid form where multiple records can be modified at once. There is only one form on the page to submit all records.
<f:if condition="{records}">
<f:then>
<f:form action="update" enctype="multipart/form-data" name="updateRecords" object="{records}">
<div class="row">
<f:for each="{records}" as="element" iteration="recordsIterator">
<div class="col-md-3">
<h5>{element.title}</h5>
<div>
<f:if condition="{feature}">
<f:then>
<h6>
<f:translate key="records.feature" />
</h6>
<f:form.checkbox property="feature" value="2" />
<label for="tx_example_records[updateRecords][{recordsIterator.index}][feature]">
<f:translate key="records.read" />
</label>
</f:then>
</f:if>
</div>
</div>
</f:for>
</div>
<f:form.submit class="button" value="{f:translate(key: 'submit', default: '[submit]')}"><input class="button" type="submit" name="" value="Submit" /></f:form.submit>
</f:form>
</f:if>
The corresponding controller has only a domain object as parameter.
/**
* action update
*
* #param \Foo\Example\Domain\Model\Records $updateRecords
* #return void
*/
public function updateAction(\Foo\Example\Domain\Model\Records $updateRecords) : void
However I need a solution with an array of all listed Domain\Model\Records passed as a parameter from the submitted form to the updateAction. The attribute feature is a checkbox to be checked if the record's value of feature = '2'; . Is this somehow possible in TYPO3? Or must I use some tricks to accomplish this task?
You can go with a Data Transfer Object here, holding the values you need to submit the form. You can find some general information related to Extbase here: https://usetypo3.com/dtos-in-extbase.html

How to render an Image coming from TYPO3\CMS\Frontend\DataProcessing\FilesProcessor in Fluid Typo3 9?

I am trying to get an Image from a custom content element into my fluid template. To achieve this I am using FilesProcessor.
custom element
Here is the corresponding code snippet from my setup.typoscript:
tt_content {
heiner_newcontentelement =< lib.contentElement
heiner_newcontentelement {
templateName = Default
dataProcessing.10 = TYPO3\CMS\Frontend\DataProcessing\FilesProcessor
dataProcessing.10 {
as = images
references.fieldName = image
references.table = tt_content
sorting = title
sorting.direction = descending
}
}
}
Showing what's available via f:debug-Viewhelper provides the following:
available variables in fluid template
So far, so good, what I have tried was to simply output the image in my fluid template with the following code:
<html data-namespace-typo3-fluid="true" xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"></html>
<f:layout name="Default" />
<f:section name="content">
<ul class="Das ist gut">
<f:for each="{images}" as="image">
<f:debug>{image}</f:debug>
<f:image image="{image}" height="250c" width="200c"/>
</f:for>
</ul>
</f:section>
</html>
although the variable "image" in the for-each loop is not empty, the image-viewhelper wont render anything. I am so desperate :( Somebody knows whats going wrong here? A lot of thx :)
According to the documentation, File Reference information are not always available in the fluidtemplate (see also https://docs.typo3.org/m/typo3/reference-coreapi/9.5/en-us/ApiOverview/Fal/UsingFal/Frontend.html#fluidtemplate).
What happens if you try this:
<ul class="Das ist gut">
<f:for each="{images}" as="image">
<f:debug>{image}</f:debug>
<f:image image="{image.originalFile}" height="250c" width="200c"/>
</f:for>
</ul>

Check if pid of current page is X

How can I check if a page has a specific ID, and if true output a text?
I thought about something like this (pseudocode):
<f:if condition="{current.page.uid}=='78'">
<p>I am Page 78</p>
</f:if>
If you want to use this in an FLUIDTEMPLATE (page.10 = FLUIDTEMPLATE as example) you can access the page data with {data.uid}.
<f:if condition="{data.uid} == 78">
<p>I am Page 78</p>
</f:if>
In an extbase Extension you can make it like #dimitri-l says.
You can fetch current page ID via typoscript object
typoscript:
lib.currentPageId = TEXT
lib.currentPageId.data = TSFE:id
FLUID:
<f:if condition="{f:cObject(typoscriptObjectPath:'lib.currentPageId')}==78">
<p>I am Page 78</p>
</f:if>
You can make a variable into your "page TS setup" like here :
variables {
pageUid = TEXT
pageUid.field = uid
...
}
So you can make your fluid condition as here :
<f:if condition="{pageUid}=={settings.homepid}">
<p>I am Page 78</p>
</f:if>
for exemple...
You would need to pass the page id to the fluid template. If you are using an Extbase controller you can pass $GLOBALS['TSFE']->id to your view and then use an if condition as you did.
$this->view->assign('pageId', $GLOBALS['TSFE']->id);
I am not sure if it is already possible to do string comparison in Typo3 6.2, if not, you have to compare it that way:
<f:if condition="{0:pageId} == {0:'78'}>
...
</f:if>
Otherwise this is a clean solution for current versions
<f:if condition="{pageId} == '78'>
...
</f:if>
With the VHS viewhelper you can do it with fluid only, no need for a Typoscript helper:
{namespace v=FluidTYPO3\Vhs\ViewHelpers}
<f:if condition="{v:page.info(field: 'uid')} == '21'">
<f:then>
Shows only if page ID equals 21.
</f:then>
</f:if>
Sometimes you need to give a link a class when the link target is the current page (here: uid=1). The inline version helps:
<f:link.page pageUid="1"
class="{f:if(condition: '{data.uid} == 1', then: ' current')}">
Link
</f:link.page>

Get layout name in front end - fluid typo3

I have a fluid typo3 site with single page layout.One menu have different layout.How to get the selected layout name in my main template?
main.html
<v:page.menu levels="1" as="sections">
<f:for each="{sections}" as="section" iteration="itemIteration">
<f:debug>{sections}</f:debug>
</f:for>
</v:page.menu>
sub.html
<f:layout name="Pagewithnav" />
<f:section name="Configuration">
<flux:form id="subnav" icon="{f:uri.resource(path: 'Icons/Page/logo.png')}" label="Sub Navigation">
<!-- Insert fields, sheets, grid, form section objects etc. here, in this flux:form tag -->
</flux:form>
<flux:grid>
<!-- Edit this grid to change the "backend layout" structure -->
<flux:grid.row>
<flux:grid.column colPos="0" colspan="4" name="main" label="Navigation wrapper" />
</flux:grid.row>
<flux:grid.row>
<flux:grid.column colPos="1" colspan="4" name="main" label="Main wrapper" />
</flux:grid.row>
</flux:grid>
</f:section>
<f:section name="Main">
<div class="sub_nav">
<div class="container">
<v:content.render column="0"/>
</div>
</div>
<div class="container">
<v:content.render column="1"/>
</div>
</f:section>
It depends on what exactly you mean by "Layout name":
If you mean fields of the pages table for each individual page then those will be available in each record when you iterate it in v:page.menu (for example, tx_fed_page_controller_action).
If you mean fields of pages but also when this variable is inherited (for example, backend_layout is and tx_fed_page_controller_action is as well, but each through different methods) it becomes more complex: you would need to walk through the root line and use the first non-empty value. For that, v:page.rootLine plus v:iterator.filter plus v:iterator.first can be of great help (put output from root line into filter to remove non-empty values then use the first VH to select the first value from that filtered result).
If you define this "layout" in a Flux form field on your page template it becomes a FlexForm variable which you can read with flux:form.data (with inheritance if not disabled and if templates match up through root line).
Depending on exactly which you mean there are quite a few possible solutions. If you are also looking for a recommendation about which one it makes sense to use: most likely you mean the layout you select in page properties (regardless of field) and for this, v:page.rootLine plus v:iterator.filter plus v:iterator.first is a nice and generic method to "slide select" any non-empty value from the root line of the current page.
You can get it with a variable in fluid
lib.templateName = TEXT
lib.templateName.stdWrap.cObject = CASE
lib.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 = Default
}
page = PAGE
page.10 = FLUIDTEMPLATE
page.10 {
#...
variables.templateName < lib.templateName
}

Typo3 Fluid - How do I check if two or more colPos have content and then print HTML

I want to print the following HTML only if one or more of the colPos has content in it. If none have content elements in it, then I don't want to print this block (the whole "row") of HTML.
<div class="row">
<div class="col-sm-4">
<f:cObject typoscriptObjectPath="lib.dynamicContent" data="5" />
</div>
<div class="col-sm-4">
<f:cObject typoscriptObjectPath="lib.dynamicContent" data="6" />
</div>
<div class="col-sm-4">
<f:cObject typoscriptObjectPath="lib.dynamicContent" data="7" />
</div>
</div>
I thought about getting the colPos and try to do a OR condition on Fluid. But I have no idea on how to do it. I know I can check one by one like this:
<f:if condition="{f:cObject(typoscriptObjectPath: 'lib.dynamicContent', data: '5')}">
...HTML for colPos 5 HERE...
</f:if>
But I don't want to do that. In my template I have almost 50 different colPos and they are organized by blocks (rows). Like colPos 1 to 5 is one block(row). colPos 10 to 25 in another block(row). But some pages will not use some blocks (rows) of colPos, so there's no reason on printing the HTML code for those blocks (rows) of colPos unused.
Thanks for your help!
A fluid-only solution would be to assign the results of the <f:cObject>-ViewHelpers each to a variable, and then use the concatenation of these variables in a condition. The v:-namespace in the example is the namespace of the extension vhs:
<v:variable.set name="col-5" value="{f:cObject(typoscriptObjectPath: 'lib.dynamicContent', data: '5')}"/>
<v:variable.set name="col-6" value="{f:cObject(typoscriptObjectPath: 'lib.dynamicContent', data: '6')}"/>
<v:variable.set name="col-7" value="{f:cObject(typoscriptObjectPath: 'lib.dynamicContent', data: '7')}"/>
<f:if condition="{col-5}{col-6}{col-7}">
<div class="row">
<div class="col-sm-4">{col-5}</div>
<div class="col-sm-4">{col-6}</div>
<div class="col-sm-4">{col-7}</div>
</div>
</f:if>
You should of course move this stuff to a partial, which gets an array of the columns to print as a parameter. Then you need to write the logic only once.
Also, you should think again, if you really need 25 columns.
Since TYPO3 8.6, this is possible without extension "vhs":
<f:variable name="col-5">
<f:cObject typoscriptObjectPath="lib.dynamicContent" data="5" />
</f:variable>
<f:if condition="{col-5}">
<f:format.raw>{col-5}</f:format.raw>
</f:if>