Feature #34241
closedEXT:form - Fill SELECT with OPTIONS from static_info_tables
100%
Description
I would like to be able to pull data from a table to populate a SELECT
100 = SELECT 100 { name = ustate label { value = State } table = static_country_zones select { selectFields = zn_code, zn_name_local where = zn_country_iso_2 = 'US' orderBy = zn_name_local } }
This would be very helpful when listing large amounts of data in a form.
Updated by Björn Jacob over 9 years ago
- Category changed from Form Framework to 1602
Updated by Björn Jacob over 9 years ago
- Category changed from 1602 to Form Framework
Updated by Björn Jacob about 9 years ago
- Status changed from New to In Progress
- Assignee set to Björn Jacob
Updated by Björn Jacob about 9 years ago
- Subject changed from Fill SELECT with OPTIONS from static_info_tables to Form: Fill SELECT with OPTIONS from static_info_tables
- Status changed from In Progress to New
- Assignee deleted (
Björn Jacob)
I think this is a good idea. Having a new abstract syntax and no stdWrap support would allow the secure inclusion of data as OPTION values. We have to make sure that only certain tables are allowed for querying. That way the user is not able to select data from backend users.
Updated by Benni Mack about 9 years ago
- Target version changed from 7.5 to 8 LTS
Updated by Björn Jacob about 9 years ago
- Subject changed from Form: Fill SELECT with OPTIONS from static_info_tables to EXT:form - Fill SELECT with OPTIONS from static_info_tables
Updated by Björn Jacob over 8 years ago
- Status changed from New to Resolved
- Assignee set to Nathan L
- % Done changed from 0 to 100
This is now possible using TYPO3 7 or higher. It can be achieved by using a custom viewhelper. Since this is an example, labels are static. For sure, you can use proper functions for localization.
Create form¶
enctype = multipart/form-data method = post prefix = contact class = contact confirmation = 1 postProcessor { 1 = Mail 1 { recipientEmail = test@test.com senderEmail = test@test.com subject = Foo } } 10 = TEXTLINE 10 { label = Country Dropdown name = country partialPath = FlatElements/CountryDropdown } 20 = SUBMIT 20 { value = Submit name = submit class = button }
Create partials¶
Create new custom partials in your site package/ theme. Attention: the namespace of your viewhelper needs customization!
Resources/Private/Partials/Default/Show/FlatElements/CountryDropdown.html¶
This adds the form template (show action).
{namespace vh=Vendor\Package\ViewHelpers} <div class="row collapse csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase} {model.additionalArguments.name}"> <div class="columns label"> <label> <span class="label-text">Countries</span> <span class="form-field"> <f:form.select id="contactFormAddress" name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" options="{vh:countries(filters: {isoCodeA2: {0: 'DE', 1: 'GB'}})}" optionValueField="value" optionLabelField="label" prependOptionLabel="Select Country" prependOptionValue="" /> </span> </label> </div> </div>
The code shown below (and used above) allows to filter the drop down list accordingly. In the example, only 2 countries will be displayed (de, gb). Check out the model SJBR\StaticInfoTables\Domain\Model\Country.
options="{vh:countries(filters: {isoCodeA2: {0: 'DE', 1: 'GB'}})}"
Resources/Private/Partials/Default/Confirmation/FlatElements/CountryDropdown.html¶
This adds the confirmation template.
<f:if condition="{model.showElement}"> <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> <label>{model.additionalArguments.label}</label> {model.additionalArguments.value} </li> </f:if> <f:form.hidden class="{model.additionalArguments.class}" dir="{model.additionalArguments.dir}" id="{model.additionalArguments.id}" lang="{model.additionalArguments.lang}" style="{model.additionalArguments.style}" title="{model.additionalArguments.title}" accesskey="{model.additionalArguments.accesskey}" tabindex="{model.additionalArguments.tabindex}" onclick="{model.additionalArguments.onclick}" name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" value="{model.additionalArguments.value}" additionalAttributes="{model.htmlAttributes}" />
Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/CountryDropdown.html¶
This adds the mail template (for HTML mails).
<f:if condition="{model.showElement}"> <tr class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> <td style="width: 200px;"> <em>{model.additionalArguments.label}</em> </td> <td> {model.additionalArguments.value} </td> </tr> </f:if>
Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/CountryDropdown.html¶
This adds the mail template (for plain text mails).
{namespace form=TYPO3\CMS\Form\ViewHelpers}<f:if condition="{model.showElement}"><form:plainMail labelContent="{model}" content="{model.additionalArguments.value}" /></f:if>
Create viewhelper¶
ViewHelper Classes/ViewHelpers/CountriesViewHelper.php¶
This is the viewhelper with all the logic. Attention: do not forget to customize the viewhelper!
<?php namespace Vendor\Package\ViewHelpers; /*************************************************************** * Copyright notice * * (c) 2016 Ralf Zimmermann <ralf.zimmermann@tritum.de>, TRITUM GmbH * * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is * free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * The GNU General Public License can be found at * http://www.gnu.org/copyleft/gpl.html. * * This script is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ use TYPO3\CMS\Extbase\Persistence\Generic\Query; use TYPO3\CMS\Extbase\Persistence\QueryInterface; use TYPO3\CMS\Extbase\Reflection\ObjectAccess; use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper; class CountriesViewHelper extends AbstractViewHelper { /** * @var \SJBR\StaticInfoTables\Domain\Repository\CountryRepository */ protected $countryRepository; /** * @param \SJBR\StaticInfoTables\Domain\Repository\CountryRepository $countryRepository * @return void */ public function injectCategoryRepository(\SJBR\StaticInfoTables\Domain\Repository\CountryRepository $countryRepository) { $this->countryRepository = $countryRepository; } /** * Render * * @param array $filters * @return array */ public function render($filters = null) { $countryArray = []; $countries = $this->countryRepository->findAll(); $query = $countries->getQuery(); $query->setOrderings(array("officialNameLocal" => QueryInterface::ORDER_ASCENDING)); $this->filter($query, $filters); $countries = $query->execute(); foreach ($countries as $country) { $countryName = $country->getOfficialNameLocal(); $countryArray[] = ['label' => $countryName, 'value' => $countryName]; } return $countryArray; } /** * Filter * * @param Query $query * @param array $filters * @return void */ protected function filter(Query $query, $filters = null) { if (is_array($filters)) { $object = $this->objectManager->get($query->getType()); foreach ($filters as $filterKey => $filterValues) { if (!ObjectAccess::isPropertyGettable($object, $filterKey)) { continue; } if (is_array($filterValues)) { $query->matching( $query->logicalAnd( $query->in($filterKey, $filterValues) ) ); } } } } }
Done¶
That's it. Happy testing!
Updated by Simon Schaufelberger over 7 years ago
Can this be written into documentation? It's really hard to find that information here.
Updated by Björn Jacob over 7 years ago
This is for the old form extension (TYPO3 v7). In v8 it works differently. Since the legacy extension is not maintained anymore, we will not change the documentation. But we will add something similar for v8 to the docs.