I created a small extension that can show a puzzle game. The switchable controller actions I made include list/show (works fine), admin (also fine) and show only.
For show only I want to select a database entry from the flexform which will then be shown by the single view. For that I added a new field to the flexform:
<settings.singlePuzzle>
<TCEforms>
<label>Puzzle to show</label>
<config>
<type>select</type>
<foreign_table>tx_wspuzzle_domain_model_puzzle</foreign_table>
<items>
<numIndex index="0" type="array">
<numIndex index="0">-- Choose --</numIndex>
<numIndex index="1"></numIndex>
</numIndex>
</items>
<size>1</size>
<maxitems>1</maxitems>
<minitems>0</minitems>
</config>
</TCEforms>
</settings.singlePuzzle>
So far so good, if I select an item here and debug it in the list view it seems to select the correct id.
Now I changed the showAction in the controller to look like this:
/**
* action show
*
* #param \Websafari\Wspuzzle\Domain\Model\Puzzle $puzzle
* #return void
*/
public function showAction(\Websafari\Wspuzzle\Domain\Model\Puzzle $puzzle = NULL) {
if(is_null($puzzle)) $puzzle = $this->puzzleRepository->findByUid($this->settings['singlePuzzle']);
$this->view->assign('puzzle', $puzzle);
}
So now I change the action to "show only", select an entry for "singlePuzzle" and then (I think) I should be good to go, but all I get ist the following error:
Required argument "puzzle" is not set.
Obviously I made a mistake, but I don't get it.
First: Why is "puzzle" still required? That's why I added "= NULL" to the function (I also tried adding #ignorevalidation $puzzle to the comment).
Second: Why is it not set? When I debug "$this->settings['singlePuzzle'];" I get an id for a puzzle object.
Would be great if someone could point out my error, because I'm really stuck here. Thnx a lot!
The problem is that the reflection information of a class (arguments etc.) are cached in Extbase. So if you change the definition and don't clear the respective cache, it still will require your argument.
You need to clear the "System caches" in TYPO3. There are three ways to do it:
If you are in development context, you will have the button (with the red flash icon) in the backend.
You can enable the button through User TSconfig in production context using options.clearCache.system = 1.
A button for clearing the system cache is in the install tool, section "Important actions".
You can also manually clear all cache related tables in PhpMyAdmin
TRUNCATE table cf_cache_hash;
TRUNCATE table cf_cache_hash_tags;
TRUNCATE table cf_cache_pages;
TRUNCATE table cf_cache_pagesection;
TRUNCATE table cf_cache_pagesection_tags;
TRUNCATE table cf_cache_pages_tags;
TRUNCATE table cf_cache_rootline;
TRUNCATE table cf_cache_rootline_tags;
TRUNCATE table cf_extbase_object;
TRUNCATE table cf_extbase_object_tags;
TRUNCATE table cf_extbase_reflection;
TRUNCATE table cf_extbase_reflection_tags;
TRUNCATE cf_extbase_typo3dbbackend_queries;
TRUNCATE cf_extbase_typo3dbbackend_queries_tags;
TRUNCATE cf_extbase_typo3dbbackend_tablecolumns;
TRUNCATE cf_extbase_typo3dbbackend_tablecolumns_tags;
TRUNCATE cf_extbase_datamapfactory_datamap;
TRUNCATE cf_extbase_datamapfactory_datamap_tags;
This also truncates query cache etc. what can be useful in some situation.
As soon as the cache is cleared, it should work.
BTW, just to be on the safe side, you should typecast the UID from FlexForm:
if(is_null($puzzle)) $puzzle = $this->puzzleRepository->findByUid((int)$this->settings['singlePuzzle']);
Related
situation:
2 diferent tables, 1 view;
want to achieve:
I've got to change the table when I change the selectedKey in a select.
I already tried to create fragments with each table and call the one I want when I change the select.
fragment1 - table 1
fragment2 - table 2
select - oEvent (onChangeSelect) - getSelectedKey - if(key === 1) - call fragment1, if(key === 2) - call fragment2, but it gives me an error.
I don't know if this is correct and I'm not finding any infos related online.
If someone can show some links or give me just an idea on how can I do this, it would be perfect.
You could use the concept of binding to achieve this without coding. assume you have something like that in your view:
<Select><!-- ... --></Select>
<core:Fragment ... /><!-- table 1 -->
<core:Fragment ... /><!-- table 2 -->
First, add a model to your app, which will contain the information about the status of the app (which of the fragments is visible currently). Easiest way is to start with an empty JSON model. If you are familiar with manifest.json config, add it there. if not, you could add this in your Components init method:
this.setModel(new JSONModel(), "config");
This way, the new empty model is available under the name "config" in all the views of the app.
Now, we will add a visibility flag, which will control the visibility of your fragments (tables), and can be changed by the select:
<Select selectedKey="{config>/selectedFragmentKey}">
<core:Item key="" text="Please choose one" />
<core:Item key="showFragment1" text="Show Fragment 1" />
<core:Item key="showFragment2" text="Show Fragment 2" />
</Select>
This new version will store the key of the selected item in the config model in the path /selectedFragment. Add visibility flag to fragments (tables):
<!-- table 1 is only visible if "Show Fragment 1" was selected -->
<Table visible="{= ${config>/selectedFragmentKey} === 'showFragment1'}" .../>
<!-- table 2 is only visible if "Show Fragment 2" was selected -->
<Table visible="{= ${config>/selectedFragmentKey} === 'showFragment2'}" .../>
and you're done.
Main lesson here: learn to use bindings.
If I understood the question correctly, you have a selection control (which has 2 entries), and a table in the view. Based on the selection item, you want to display ONE of the tables at any given point of time. I am also assuming here, that the tables are purely used in the current view only & not really a "re-useable" thing - which gets used in different places of the app (which then renders the use of fragments an overkill).
I am assuming, both tables are bound (although to different data sets).
In that case, consider using the "visible" property of the appropriate table to "false".
Remember - all UI components, including tables inherit from sap.ui.core.Control - which has the "visible" property.
In API reference for table : https://sapui5.hana.ondemand.com/#/api/sap.ui.table.Table%23methods/Summary
If you scroll down to "Borrowed from:" section, you will see the "setVisible" and "getVisibe" methods.
So, in the event fired during selection change, you can grab the table control & set the visibility using the aforementioned methods.
Alternatively, you can also set an expression binding directly on the table control in XML, which evaluates to "true" or "false" (perhaps using a formatter).
Let me know if you need further info on this.
Best Regards,
Gopal Nair.
I am writing a Typo3 extension with custom content elements using Flexforms. All is working fine.
I just would like to add a value to "header" inside of tt_content just like the standard Typo3 content elements do. That way, if I create a translation, the default header of the translated content should show as "My headline (copy 1)" and not just as "(copy 1)". Also, the header should show up if I try and add an anchor link to the element.
For example, my flexform starts like this:
<T3DataStructure>
<sheets>
<sGeneral>
<ROOT>
<TCEforms>
<sheetTitle>My Element</sheetTitle>
</TCEforms>
<type>array</type>
<el>
<headline>
<TCEforms>
<label>Text</label>
<config>
<type>input</type>
</config>
</TCEforms>
</headline>
...
I access above headline value in my HTML template like this: {flexform.sGeneral.headline}
That works well. How can I accomplish that this value also gets written to tt_content header?
I really appreciate your help.
The flexform (and all fields declared inside) are one field of the whole tt_content record. So there is a big difference whether you access a flexform field data or a data from any regular field in the record. You can't mix it up. (A field header in your flexform has no relation to the regular field header of the record)
For giving editors access to the regular header field you need to declare access for your type of tt_content (CType). This is done in the TCA-declaration.
Anyway you should have access to the header field from your FLUID as you have access to the whole tt_content record. normaly as {data.fieldname}, you might inspect with the debugger:
<f:debug title="all fluid variables">{_all}</f:debug>
Good morning
In TYPO3 7.4 the "General Storage Folder" was kicked. Before this you could use the General Storage Folder inside a plugin-flexform. You could do things like
<settings.type>
<TCEforms>
<label>Betriebsart</label>
<config>
<type>select</type>
<items type="array"></items>
<allowNonIdValues>1</allowNonIdValues>
<multiple>1</multiple>
<maxitems>99</maxitems>
<minitems>0</minitems>
<size>10</size>
<foreign_table>tx_enzhotellist_domain_model_type</foreign_table>
<foreign_label>name</foreign_label>
<foreign_table_where>AND sys_language_uid = 0 AND tx_enzhotellist_domain_model_type.pid=###STORAGE_PID###</foreign_table_where>
</config>
</TCEforms>
</settings.type>
It was possible to access the values inside General Storage Folder with help of ###STORAGE_PID###. But now this way is gone, kicked off, obsolete, whatever... Sad - really sad.
So I ask you, how to access storagePid inside plugin-flexform? (btw: typoscript-settings do not help here!)
kind regards
Johannes
You don't get this field back as it has been removed. However you can use multiple other ways, described in the manual.
###CURRENT_PID### - is the current page id (pid of the record).
###SITEROOT###
###PAGE_TSCONFIG_ID### - a value you can set from Page TSconfig dynamically.
###PAGE_TSCONFIG_IDLIST### - a value you can set from Page TSconfig dynamically.
###PAGE_TSCONFIG_STR### - a value you can set from Page TSconfig dynamically.
I'd like to display forms per agency. To achieve this, I want to select one agency on the frontend plugin (with a flexform) and then, when I have chosen one, the flexform reloads with<onChange>reload</onChange> so I get the filtered records.
Problem
How can I access flexform-values in another select-block? My general idea is to use the <foreign_table_where></foreign_table_where> part to limit this. But I cant access previous set values (unlike I do it in the <displayCond></displayCond> block with FIELD:mySetting). My form-part looks like this:
Form
<config>
<type>select</type>
<foreign_table>foreignTableForm</foreign_table>
<foreign_table_where>HOW TO DO?</foreign_table_where>
<minitems>0</minitems>
<maxitems>10</maxitems>
<multiple>0</multiple>
<size>5</size>
<itemListStyle>Width:250px</itemListStyle>
</config>
Agency
<config>
<type>select</type>
<foreign_table>foreignTableAgency</foreign_table>
<minitems>0</minitems>
<maxitems>10</maxitems>
<multiple>0</multiple>
<size>5</size>
<itemListStyle>Width:250px</itemListStyle>
</config>
Goal
Get values from agency foreign table (works)
As I have clicked on that specific agency, the flexform reloads (works)
Only those forms get listed, which have the foreign key equal to the agency's uid previously set after the reload (how to achieve this?)
Thanks for any help!
You need to use a hook to modify the flexform in the fly. Please check ext:news on how to archive this. It does something similar to trim the flexform to only show valid field in the current selected context.
How do I select an item from storage folder, when including a frontend plugin as content element?
I have made an extension (or am trying to make), that will save blocks in a folder, that can be used on several pages.
When adding a frontend plugin to a page, and selecting the extension, I want to be able to select a record that should be displayed there...
I've been trying to set up Flexforms, but still haven't got any result.
Thanks
Yes, the FlexForm is the typical place to store additional settings of inserted plugin and most comfortable for normal BE editors.
On the other hand, if you are the only one who'll administrate that page (with full admin access) and you don't need to paste this plugin more than once on the page you can also save the uid of the default record in TypoScript - setup field of the template included on the required page.
Something like
plugin.tx_yourext_pi1.initialRecordUid=123
or for Extbase
plugin.tx_yourext.settings.initialRecordUid=123
While you didn't tell us how are you gonna to create the extension, we can't help you better.
There is a content element called "insert records". Perhaps that is, what you need?
If you need your extension, just paste some code. It is easier to help then.
If you want to do it by flexform you can use following way,
<selectProperty>
<TCEforms>
<label>Select property</label>
<displayCond>FIELD:WhichPage:=:Home</displayCond>
<config>
<type>select</type>
<foreign_table>Your table name</foreign_table>
<foreign_table_where>AND (your table name.deleted = 0) AND (your table name.hidden = 0) AND (tx_wellnessproperty_property.sys_language_uid = CAST('###REC_FIELD_sys_language_uid###' AS UNSIGNED) OR sys_language_uid = '-1' ) ORDER BY your table name.uid DESC </foreign_table_where>
<size>3</size>
<minitems>0</minitems>
<maxitems>3</maxitems>
</config>
</TCEforms>
</selectProperty>
By using this flexform method you can select records individually with every plugin..