How to select and store ContentElement UID in Flux FlexForm Configuration? - typo3

I'm currently building a TYPO3 PageTemplate with Flux and Fluidpages (both GitHub Master-Branch).
I'd like to have the possibility to select a number of ContentElements from the PageTree and store the UIDs in a variable for later rendering.
My first approach combining a Flux TreeField with a RelationField:
<flux:form.sheet name="content" label="content settings">
<flux:field.tree
name="treetest"
label="treetest"
table="pages"
parentField="pid"
foreignLabel="title"
multiple="true"
minItems="0"
maxItems="1000"
size="8"
expandAll="false"
/>
<flux:field.relation
name="relationtest"
label="relationtest"
table="tt_content"
condition="AND tt_content.pid IN ({treetest})"
multiple="true"
size="8"
minItems="0"
maxItems="3"
/>
</flux:form.sheet>
This sadly results in a SQL-Error because the last condition is inserted as:
AND tt_content.pid IN (60|foo)
Where 'foo' is the title of a SysFolder with the UID 60.
Debug-Output in the frontend prints the field 'treetest' as:
treetest => '60' (2 chars)
and the condition for the field 'relationtest' as:
condition => 'AND tt_content.pid IN (60)' (26 chars)
Questions:
As a matter of fact, I'm missing something here and I'd appreciate any hint, where the crux is here?
Is there maybe a different solution to select a ContentElement from the PageTree?

1) It is possible that you have either a default value, an inherited value or somehow disconnected XML which contains the other value. To be 100% sure none of these are your cause, try the same on a completely new page. The expected result of your code and selecting a page UID, is exactly the value 60 - nothing more, nothing less.
2) You may find it easier to use a ###STORAGE_PID### marker in your foreign_table_where and selecting the page(s) allowed for content selection, as values in the Behavior tab when editing your content element or page. This value has the added benefit of being possible to allow only for certain users or usergroups, or admins only.

Related

How to have multiple sections with images in a FluidTYPO3 flux form with TYPO3 10?

I have been using FluidTYPO3 (flux and vhs) to run TYPO3 web pages for many years now. With TYPO3 10, I face a major problem. I'll quickly write about my use case, how I solved it so far, and then what the problem with 10 LTS is.
Use case:
I want to have a content element template for a timeline using FluidTYPO3/flux. Each "point" on the timeline should have a heading, some text, and optionally some images. All in all, pretty basic (or so I thought).
Solution so far (TYPO3 <= 9):
Timeline elements are sections. Images are using flux:field.file.
Simplified example of the form:
<flux:form id="timeline" label="timeline">
<flux:form.section name="timeline" label="Timeline">
<flux:form.object name="element" label="Element">
<flux:field.input name="title" label="Heading" />
<flux:field.text name="label" label="Text" enableRichText="TRUE" />
<flux:field.file name="images" label="Pictures" allowed="jpg,png,svg" multiple="TRUE" maxItems="50" size="5" showThumbnails="TRUE"
/>
</flux:form.object>
</flux:form.section>
</flux:form>
With this, multiple elements can be created on the timeline and each of them can have its own set of images.
Problem in TYPO3 10:
The technology (TCA group fields to select files) that flux:field.file relies on was deprecated in TYPO3 9 and removed in TYPO3 10, see this notice. That is one of the reasons why flux:field.file was also marked deprecated and is going to be removed in TYPO3 10.
The TYPO3 deprecation notice says to use FAL relations instead. Of course, flux can also do this with flux:field.inline.fal. However, you can only have one FAL field per FlexForm. This precludes its usage in sections, since all sections would share the same images. This limitation is known for some time - see this bug report for example - but has never been fixed. It is also why I initially chose not to use FAL fields. Using bare file fields was the recommended workaround at the time.
Question:
So - how is everyone doing it? How to add multiple image fields to a flexform in TYPO3 10?
EDIT: More specifically, how to add an image field as part of a Flexform section that can contain multiple child records (resulting in multiple image fields)?
Note: I know that I can get a "file-like" field back by using an input field with inputLink renderType (like this), but as far as I can tell it does not allow to link multiple images.
I've found another workaround that might be appropriate for some use cases:
It is still possible to use flux:field.file fields if the useFalRelation parameter set to true, even on TYPO3 v10 LTS and in repeatable FlexForm sections. This will then put sys_file record IDs separated by comma into the field instead of raw filenames. They can be used as src argument for, e.g., f:image just as well as the filename, so the CE templates itself do not have to be modified. All existing CEs that had useFalRelation set to false need to be migrated though so that the filenames are replaced with sys_file UIDs.
This is a bit better than the inputLink workaround since it allows multiple images.
It seems the only workaround with TYPO3 core onboard methods is to go for a Flux-Container having a single column containing simple default "Text with image" or "text with media" elements and then to just ignore additional options of those elements and to just render the necessary fields.
With Gridelements this is called a "functional container", since the container determines the behaviour and appearance of those elements, while the elements themselves don't have to be custom elements at all.
Additionally this makes access to the content of those elements - i.e. while doing a search query - much easier.
The bug report you mentioned already contains the solutions, since the actual problem described there is that FAL fields in a flexform are using the same name.
So instead of
image
according to the bug report there should be
settings.foreground.image
which is of course not working, since the dot is part of the path but not of the name.
But actually replacing the dot with an underscore and using some suffixes within the same flexform tab should do the trick:
settings.foreground.settings_foreground_image
settings.foreground.settings_foreground_image2
This way you make sure that
The field names within your flexform are unique
The actual field name within the sys_file_reference entry already contains the full path information
You can use that information to fetch images i.e. within a DataProcessor and still know the FlexForm field they actually belong to
Sitll I would recommend to fully move away form FlexForms (and thus Flux too) in favor of "real" fields in the database table.
If you currently use the flux:field.file element at typo3 10 with the useFalRelation=1 you can replace it by the flux:field element. It is not deprecated and works in combination with the flux:form.object element
Following example:
<flux:field.file
allowed="jpg,png,svg,gif"
exclude="false"
label="MyLabel"
name="myname"
showThumbnails="1"
useFalRelation="1"
maxItems="1"
minItems="1"
/>
Can be replaced with:
<flux:field type="input" name="myname" label="MyLabel"
config="{
type: 'group',
size: 1,
internal_type: 'db',
use_fal_relation: 1,
allowed: 'sys_file',
maxitems: 1,
minitems: 0,
show_thumbs: 1,
appearance: {
elementBrowserAllowed: 'jpg,png,svg,gif',
elementBrowserType: 'file'
}
}
"/>

How do I fetch the UID of a page that's been selected with flux:wizard.link?

I'm using the flux:wizard.link to select a page from the page tree in Typo3:
<flux:field.input name="page_id" label="Select page">
<flux:wizard.link activeTab="page"/>
</flux:field.input>
Now, I want to fetch this page and render it in a container.
<v:content.render pageUid="{page_id}" />
But the {page_id} has the t3-link saved instead of the expected pageUID (e.g. t3://page?uid=125)
How do I extract the page's UID?
I could let the user enter just the page-id in an input-field, but I'd rather have her select the page via wizard...
One solution could be to cut the string into two parts:
<v:iterator.explode content="{page_id}" glue="uid=" as="newarray">
{newarray.1}
</v:iterator.explode>
The string page_id is cut at the phrase 'uid=' into two parts, which are saved in the array newarray. With {newarray.1} you can output the second part of the array.
This is most likely not the best solution. It depends on the link which should have always the same structure (containing 'uid=xxx'). But so far it seems to be the only way.

Best way to declare content element uids to use them in fluid templates

I want to display some contentlement on every page with fluid templates. My solution was to create a typoscript element like:
lib.my.myelement= CONTENT
lib.my.myelement {
table = tt_content
select {
pidInList = 15
where = uid=99
}
}
and then use it in the fluid template with:
<f:cObject typoscriptObjectPath="lib.my.myelement" />
Another way is to create them directly in fluid with v:content.render or v:content.get. In this example I get all content elements on one page and save them in an array:
<v:variable.set name="contentElements" value="{v:content.get(column:'0', limit:'3', pageUid:'9', render:'FALSE')}" />
I can not use the first solution, cause on this page there will be much different languages ( I could use it, but every time a new language is added I would have work to declare all new uids of the new elements in typoscript).
The second solution would work better, cause when you translate a page the element uids change, but the pageUid does not change. But here I have the problem that I don't just need all elements, I also have to identify each element.
Here is how I use the second solution:
<v:variable.set name="contentElements" value="{v:content.get(column:'0', limit:'3', pageUid:'9', render:'FALSE')}" />
<f:for each="{contentElements}" as="contentElement" iteration="footerIteration">
<div class="column{v:math.sum(a: footerIteration.index, b: 1)}">
<v:content.render contentUids="{0:contentElement.uid}" />
</div>
</f:for>
As you can see, I use every element the same way.
lets create a simple case:
I have a page with the pageUid = 10 (this page will have translations). On every of this translations will be 3 elements. Lets say 1 element got the "id" (with id I mean something how I can identify this element) title1 and the other two elements have the id list1 and list2.
And my question now is How could I access for example list1?
I hope its understandable, if something is not clear please leave a comment.
Edit: I could use the same order on every translation for the elements and then check the iteration in the for-loop (see the second solution) to identify them. But I wonder if there a better, cleaner way.

Is there a way to deliberately make a form field that doesn't submit?

A lot of folks on Stack Overflow are probably trying to fix forms that don't submit, but I'm actually hoping to do the opposite!
What I'd like to do for an art project is make a form with a "joke" field -- say, your SSN, your bank account number, your fingerprints or retina scans or DNA code, or something super personal like that. But I don't want the number in our server logs, and I don't want it to be transmitted over the internet at all. I don't want any legal liability!
Basically the idea is just to ask for something audacious, but not to handle the data that may or may not come from users who actually put it in.
So, is there a way to make a field that acts as a normal form field, but where nonetheless we would feel "safe" that users who actually do put their sensitive info in the field will be protected?
What's the "safest" approach to something like this?
Form fields require a name to be submitted:
If any of the following conditions are met, then skip these substeps for this element:
[…]
The field element is not an input element whose type attribute is in the Image Button state, and either the field element does not have a name attribute specified, or its name attribute's value is the empty string.
[…]
So you could simply use an input without name attribute:
<input type="text">
Be careful with your "jokes", if you want that the information of the field is not submitted, then, you can simply leave it out of the form element like this:
<form action="... >
<input type="... >
</form>
<input type="... > <!-- This field won't be submitted-->

Grails - how to hide a date inside a form

I have an 'edit' view for a model that has several fields (one of which is a date). I only want a few of the fields visible to allow edits, so I just hide the other fields using <g:hiddenField>
But one of the fields is of type TimeStamp and I can't seem to find a way to hide this in the form. I tried
<g:form method="post" >
<g:textField name="firstName" value="${applicationUserInstance?.firstName}" />
<g:textField name="lastName" value="${applicationUserInstance?.lastName}" />
<g:datePicker name="createDate" style="visibility:hidden;" precision="day" value="${applicationUserInstance.createDate}" />
The date picker is still visible. Any idea how to hide the date so that I can just pass this to the update method upon submit of the form. Many thanks.
Just re-iterating Rob's comment here. No need to put that on the form. The only data you need on the form is the data you are updating and the ID of what is being updated. Everything else will just stay the same...
def update = {
def applicationUserInstance = User.get(param.id)
// at this point applicationUserInstance.createDate is
// correct.
applicationUserInstance.properties = params
// since no createDate was in the params, it doesn't change.
// so you're good
applicationUserInstance.save(flush:true)
}
Actually my answer below might not be the right answer to your question. Otherwise if you really just have a createdDate-field, which should keep track, when the entry was created in the database, I suggest you do it the Grails-way and use the reserved keywords 'dateCreated' and 'lastUpdated'
Check http://grails.org/doc/1.3.7/guide/5.%20Object%20Relational%20Mapping%20(GORM).html#5.5.1 Events and Auto Timestamping
on how to use these. If you use these then my answer below will be helpful to control the visibility of these fields 'dateCreated', 'lastUpdated'
Suggestions for 'dateCreated', 'lastUpdated'
Probably you want this timestamp to be created automatically as you found it in the Grails documentation but you do not want it to be visible in your view.
Now, to exclude this timestamp from being visible, first
grails install-templates
I assume you have grails-1.3.7
Go to src/templates/scaffolding and check your gsp-files, e.g. 'create' and 'edit'
Search for this line:
<% excludedProps = ["version", "id",
and edit for example 'dateCreated'
<% excludedProps = ["dateCreated", "version", "id",
There is also a tutorial on this topic http://www.ibm.com/developerworks/java/library/j-grails01209/index.html
Greetings,
Jan