I'd like to get a solution for the TYPO3 EXT:gridelements.
I need gridelements in gridelements (nested) for Bootstrap Tab´s:
Grid Container Outer
Grid Container 1
Text with Image
Text
Text with Image
Grid Container 2
Text
Text with Image
with a foreach-loop (debug) it works for output from the grid-containers, but it renders Grid Container 1 and Grid Container 2 together in one gridelements col.
I need the output separated and would appreciate any help.
In your TypoScript file you've probably to set the proper path to the gridelement template:
tt_content.gridelements_pi1.20.10.setup {
TwoColumns < lib.gridelements.defaultGridSetup
TwoColumns {
cObject = FLUIDTEMPLATE
cObject {
file = Ext:path/to_your/template/template_name.html
}
}
The template file can look somehow like this:
<div class="row justify-content-md-center">
<div class="col-md-6">
<f:format.raw>{data.tx_gridelements_view_column_11}</f:format.raw>
</div>
<div class="col-md-6">
<f:format.raw>{data.tx_gridelements_view_column_12}</f:format.raw>
</div>
</div>
And make sure your grid columns colPos parameter are equal to tx_gridelements_view_column_... in the template.
Related
I use TYPO3 v10.4.8 with the extension gridelements and the core form extension. I have included the form into my created grid element in the backend, but it's not visible in frontend. This is a part of my grid template:
<f:if condition="{children}">
<f:for each="{children}" as="columns" key="rowNumber">
<div class="row grid-row grid-row-{rowNumber}">
<f:if condition="{columns}">
<f:for each="{columns}" as="column" key="columnNumber">
<div class="col-12 grid-column grid-column-{columnNumber}">
<f:for each="{column}" as="child">
<div class="inner">
<f:cObject typoscriptObjectPath="tt_content.{child.data.CType}" data="{child.data}" table="tt_content" />
</div>
</f:for>
</div>
</f:for>
</f:if>
</div>
</f:for>
</f:if>
My configuration:
lib.gridelements.defaultGridSetup =< lib.contentElement
lib.gridelements.defaultGridSetup {
templateName.field = tx_gridelements_backend_layout
templateName.ifEmpty = GridElement
layoutRootPaths {
10 = EXT:gridelements/Resources/Private/Layouts/
20 = {$page.fluidtemplate.templateRootPath}
}
partialRootPaths {
10 = EXT:gridelements/Resources/Private/Partials/
20 = {$page.fluidtemplate.templateRootPath}
}
templateRootPaths {
10 = EXT:gridelements/Resources/Private/Templates/
20 = {$page.fluidtemplate.templateRootPath}
}
dataProcessing {
10 = GridElementsTeam\Gridelements\DataProcessing\GridChildrenProcessor
10 {
default {
as = children
options {
resolveChildFlexFormData = 0
}
}
}
}
}
The Render.html file from the core module is called, but the variable formConfiguration is empty, so no form is rendered.
Since a form element uses the pi_flexform field to select the form definition, you have to disable the automatic FlexForm resolver of Gridelements.
By default Gridelements with dataProcessing is meant to be rendering everything within a FLUID template by accessing variables and settings directly. So the default setting of the DataProcessor is to resolve FlexForm XML data into arrays.
To disable that behaviour you can use the option
resolveFlexFormData = 0
to disable it for a container and its children or
resolveChildFlexFormData = 0
to still resolve container FlexForms but skip those of child elements.
I have to make a backend and a frontend-layout with grid-elements. To clarify it a bit: I have 10 containers, 5x2
It looks in the backend like this:
con 1_1 | con 2_1 | con 3_1 | con 4_1 | con 5_1
con 1_2 | con 2_2 | con 3_2 | con 4_2 | con 5_2
(con stands for container)
There might be smarter ways to realize this, maybei with just "text with image"-content elements, but in this case this was the requirement.
Now the problematic part. I need to wrap each container differently. My expected output is something like this:
<div class="left w-clearfix">
<div class="organe_50_stapel_logo">
IMAGE // works
</div>
<div class="organe_50_stapel_text">
TEXT // works
</div>
</div>
(2nd - 4th container would be wrapped in "middle" and the 5th container in "right).
Now for my setup, I get the fields wrapped (marked with // works), however, I'm stuck wrapping certain fields which belong together.
Here is my setup:
21 < lib.gridelements.defaultGridSetup
21 {
columns {
11 < .default
11.wrap = <div class="organe_50_stapel_logo">|</div>
12 < .default
12.wrap = <div class="organe_50_stapel_logo">|</div>
13 < .default
13.wrap = <div class="organe_50_stapel_logo">|</div>
14 < .default
14.wrap = <div class="organe_50_stapel_logo">|</div>
15 < .default
15.wrap = <div class="organe_50_stapel_logo">|</div>
21 < .default
21.wrap = <div class="organe_50_stapel_text">|</div>
22 < .default
22.wrap = <div class="organe_50_stapel_text">|</div>
23 < .default
23.wrap = <div class="organe_50_stapel_text">|</div>
24 < .default
24.wrap = <div class="organe_50_stapel_text">|</div>
25 < .default
25.wrap = <div class="organe_50_stapel_text">|</div>
}
}
11 + 21 belongs in the container "left"
12,13,14,22,23,24 in the container "middle"
15,25 in the container "right"
You should go for another approach in this case and get rid of the individual wraps for the columns in favor of an overall cObject making use of the so called "virtual fields" of Gridelements.
These fields get filled with content during the rendering process and then made available via cObj->data, thus accessiable via TypoScript field, data, insertData and dataWrap as well as variables within a FLUIDTEMPLATE.
21 < lib.gridelements.defaultGridSetup
21 {
cObject = TEXT
cObject {
dataWrap (
<div class="left w-clearfix">
<div class="organe_50_stapel_logo">{field:tx_gridelements_view_column_11}</div>
<div class="organe_50_stapel_text">{field:tx_gridelements_view_column_21}</div>
</div>
<div class="middle">
<div class="organe_50_stapel_logo">{field:tx_gridelements_view_column_12}</div>
<div class="organe_50_stapel_text">{field:tx_gridelements_view_column_22}</div>
</div>
<div class="middle">
<div class="organe_50_stapel_logo">{field:tx_gridelements_view_column_13}</div>
<div class="organe_50_stapel_text">{field:tx_gridelements_view_column_23}</div>
</div>
<div class="middle">
<div class="organe_50_stapel_logo">{field:tx_gridelements_view_column_14}</div>
<div class="organe_50_stapel_text">{field:tx_gridelements_view_column_24}</div>
</div>
<div class="right">
<div class="organe_50_stapel_logo">{field:tx_gridelements_view_column_15}</div>
<div class="organe_50_stapel_text">{field:tx_gridelements_view_column_25}</div>
</div>
)
}
}
This is working for flexform_fieldname, parentgrid_fieldname, tx_gridelements_view_column_123 and tx_gridelements_view_child_123. Additionally there are tx_gridelements_view_children and tx_gridelements_view_columns, but these contain arrays for the FLUIDTEMPLATE people, since TypoScript can't deal with arrays.
The fields are called "virtual" because they don't exist in the database, but will be filled into cObj->data during the rendering process. Still you can do anything with them that can be done with real fields, except writing them back to the database.
See https://docs.typo3.org/typo3cms/extensions/gridelements/Chapters/Typoscript/Reference/Index.html for the TypoScript Reference describing those fields.
I have got similar error in gridelement by rending using typoscript.
I have used exact TypoScript which you used !
Please add this line in your template > setup at last
tt_content.gridelements_pi1.20 = COA
My problem solved by adding this line , I hope it will help you !
EXT : gridelements 8.0.0-dev
TYPO3 : 8.7.8
Thanks :)
Is there a way to have the Frontend layout determine the Backend layout, template file and columns?
At the moment I have the following code that allows you to set the Backend layout and it uses the appropriate template file. But this gets very messy when there are different column positions for each layout.
page.10 = FLUIDTEMPLATE
page.10 {
#format = html
file= fileadmin/templates/example/partials/example_home.html
partialRootPath = fileadmin/templates/example/partials/
layoutRootPath = fileadmin/templates/example/layouts/
variables {
# Assign the Columns
main < styles.content.get
main.select.where = colPos = 0
news < styles.content.get
news.select.where = colPos = 1
}
}
}
# Assign the Template files with the Fluid Backend-Template
page.10.file.stdWrap.cObject = CASE
page.10.file.stdWrap.cObject {
key.data = levelfield:-1, backend_layout_next_level, slide
key.override.field = backend_layout
# Set the default Template
default = TEXT
default.value = fileadmin/templates/example/partials/example_home.html
# Set a second Template
23 = TEXT
23.value = fileadmin/templates/example/partials/example_internal.html
}
Not messy at all, here's a real world example:
page.10 = FLUIDTEMPLATE
page.10 {
file.stdWrap.cObject = CASE
file.stdWrap.cObject {
key.data = pagelayout
default = TEXT
default.value = {$customPagesTemplatePath}/Standard.html
1 = TEXT
1.value = {$customPagesTemplatePath}/Home.html
2 = TEXT
2.value = {$customPagesTemplatePath}/Landing.html
10 = TEXT
10.value = {$customPagesTemplatePath}/NewsDetail.html
11 = TEXT
11.value = {$customPagesTemplatePath}/LandingMini.html
12 = TEXT
12.value = {$customPagesTemplatePath}/FullWidth.html
}
layoutRootPath = {$customPagesLayoutPath}
partialRootPath = {$customPagesPartialPath}
}
Think about it like this:
As you say, forget about frontend layout. That's legacy; be layout serves for BE and FE.
If a page was a city, the colPos would be the street. Or rather, imagine the Backend is a map you're drawing, and the frontend is a LEGO City you build according tho that map :-)) If it's OK, I'll stick with that metaphor.
ColPos is a determined part of a page where a record lives. If you can, take a look at the tt_content table in the database: you'll see that colPos is just a column with a number. So in the city "Page 1", there's a street called "colPos 7", and it contains some records (those would be houses). With the be_layout wizard in TYPO3 you'll create an administrative map of that city: how the editor should see these streets.
In the FLUIDTEMPLATE you call depending on the selected be_layout, you will create the city itself; the rendered frontend.
Here's another real world example for such a fluid template (Home.html):
<f:render partial="Mobilenav" />
<f:render partial="Header"/>
<div class="row">
<f:cObject typoscriptObjectPath="lib.home-teaser" />
</div>
<aside>
<div class="row">
<div class="columns">
<div class="row">
<div class="fp-teaser-outer small-48 medium-24 large-12 columns">
<div class="fp-teaser-box-wrapper">
<f:cObject typoscriptObjectPath="lib.home-something" />
</div>
</div>
<div class="fp-teaser-outer small-48 medium-24 large-12 columns">
<div class="fp-teaser-box-wrapper">
<f:cObject typoscriptObjectPath="lib.home-somethingelse" />
</div>
</div>
<div class="fp-teaser-outer small-48 medium-24 large-12 columns">
<div class="fp-teaser-box-wrapper">
<div class="fp-teaser-box">
<f:cObject typoscriptObjectPath="lib.home-news-plugin-title" />
<div class="fp-teaser-hr"></div>
<div class="fp-teaser-content">
<f:cObject typoscriptObjectPath="lib.home-news" />
</div>
</div>
</div>
</div>
<div class="fp-teaser-outer small-48 medium-24 large-12 columns">
<div class="fp-teaser-box-wrapper">
<div class="fp-teaser-box">
<f:cObject typoscriptObjectPath="lib.home-blog-plugin-title" />
<div class="fp-teaser-hr"></div>
<div class="fp-teaser-content">
<f:cObject typoscriptObjectPath="lib.home-blog" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</aside>
<f:render partial="Footer"/>
... well, but where's the correlation with the colPos?
Nowhere yet! I (while being positive that there are other approaches) do this in TypoScript:
lib.home-something < styles.content.get
lib.home-something {
select.where = colPos = 7
}
So by this we prepare content for the fluid template: get all content of that page's column 7 (using the extension fluid_styled_content) and put it into a "lib" content object.
That's then inserted into the page via the f:cObject viewhelper:
<f:cObject typoscriptObjectPath="lib.home-something" />
Like this, all houses in 7th street are put into the city in exactly this location – and thus rendered in your page.
Programmatically,
$backendLayout=$GLOBALS['TSFE']->cObj->getData('pageLayout');
If None was selected in the backend [-1], it will output 'none'.
If nothing was selected it will output 'default'. Otherwise it will output the correct backend layout prefixed with your extension, taking into account subpage layouts up the page ancestry chain.
I'm having a big teaser image at the top of the page. The author may select in the backend whether the teaser image should be static or a animated slideshow. I'm using bootstrap for the slideshow btw.
The selection appears at Page > Edit > Appearance
Rootpage TSConfig:
TCEFORM.pages {
layout.altLabels.1 = Default (with Slideshow)
layout.altLabels.0 = Default
}
Now, it gets a bit trickier.
To get the Bootstrap slider running, you need to have an outer wrap and each slide wrapped, too. This is what I've got so far:
page.10.variables {
teaser < styles.content.get
teaser.select.where = colPos = 0
teaser.stdWrap.required = 1
teaser.stdWrap.wrap {
cObject = CASE
cObject {
key.field = layout
default = TEXT
default.value = |
1 = TEXT
1.value = <div id="teaser" ...>|</div> ### shortened
}
}
teaser.renderObj.stdWrap.wrap {
cObject = CASE
cObject {
key.field = layout
default = TEXT
default.value = |
1 = TEXT
1.value = <div class="item">|</div>
}
}
}
The first teaser.stdWrap.wrap works like a charm. Selecting the Frontend Layout wraps the teaser correspondingly.
But the teaser.renderObj.stdWrap.wrap doesn't want to work. Mainly, because I think that the key of the CASE is not the Frontend Layout, but the layout of the content element. How to change that?
Second question. This is how the wraps currently look like (or how they would look if the TS above would work as intended):
<div class="item">
<div id="c14">
<div class="ce-textpic ce-right ce-intext">
<div class="ce-gallery" data-ce-columns="1" data-ce-images="1">
<div class="ce-row">
<div class="ce-column">
<div class="ce-media">
<img src="img.jpg" width="1150" height="632" alt="">
</div>
</div>
</div>
</div>
<div class="ce-bodytext"></div>
</div>
</div>
Is there a way to make it look more or less like this?
<div class="item">
<img class="slide" src="img.jpg">
</div>
The customer doesn't wish to have any captions or text, so it can be ignored.
I'm running TYPO3 7.6.6 with fluid_styled_content.
So the answer for the 1st question:
You can use the "getText" data type in TypoScript. See in doc here.
It has a predefined variable for the current page record. So simple change the second key attribute so:
key.data = page:layout
But if you are running the system with fluid_styled_content, then you can simply use fluid to solve this problem. (There you can access the layout with data.layout )
To answer the second question:
Yes. It is possible, you need to take a look into the fluid_styled_content extension. There you find a lot about the templates, layouts and the elements. You can simply override them with your templates and you can get rid of any not wanted div inside.
To do so, I can recommend you a german video.
I am building a responsive front-end using Typo3 & the gridelements extension. I want to wrap each individual content element inside of a gridelement column in a wrapper, like this:
<div class="row"> <-- wrap around whole gridelements content element
<div class="column size2"> <-- wrap around gridelements column
<div class="module> <-- wrap around content inside of gridelement column
CONTENT
</div>
<div class="module>
CONTENT
</div>
</div>
</div>
If I go and put a div class="module" wrap around all ordinary content elements, then it gets wrapped TWICE- once around the gridelements "element", and once around each child content element:
<div class="module"> <-- WRONG!
<div class="row"> <-- wrap around whole gridelements content element
<div class="column size2"> <-- wrap around gridelements column
<div class="module> <-- wrap around content inside of gridelement column
CONTENT
</div>
<div class="module>
CONTENT
</div>
</div>
</div>
</div>
I guess that I can either a) wrap all content elements with div class="module", EXCEPT for content element of type gridelements, OR b) wrap children of gridelements with div class="module". What would be the best approach, and what would the TypoScript for either of these options look like?
i am not sure, but i think this is what you are looking for.
# the grid element uid
1 < lib.gridelements.defaultGridSetup
1 {
columns {
# colPos ID
10 < .default
10.wrap = <div class="row">|</div>
# this adds the value "module" as class and wraps a content element
# which is inside this grid. (like a replace for csc-default)
default.renderObj.20 {
stdWrap.innerWrap.cObject.default.20.10.value = module
}
}
}
maybe there is a better solution. if so, let me know
EDIT:
hmm, i slightly misunderstood the whole thing, so i changed a bit :P