aemka
Web-Entwicklung, Design, TYPO3, Magento

+494104960039
info@aemka.de
www.aemka.de

Länder Auswahl Dropdown im TYPO3 9 Form Framework

In TYPO3 9 enthält das TYPO3 eigene Kontakt Formular System "Form Framework" (EXT:form) zwar bereits 22 Element Typen, die man beim Erstellen von Formularen benutzen kann. Ein Dropdown Element, bei dem der Nutzer im Formular sein Land aus einer Länderliste auswählen kann, ist aber leider nicht mit dabei, obwohl das sicher in sehr vielen Projekten immer wieder eine Anforderung ist. Daher haben wir uns an dem Artikel "How to create TYPO3 Form select element with options selected from database" von Daniel Siepmann orientiert und ein neues Formular Element entwickelt, dass diese Möglichkeit nun bietet.

Voraussetzungen

Für das folgende Beispiel basiert auf TYPO3 9 und man benötigt eine Extension, die wir im Folgenden mit EXT:extension bezeichnen. Diese kann die Extension sein, die ihr ohnehin schon im System für euer Templating als Provider Extension habt. Zusätzlich wird mindestens die Extension EXT:static_info_tables benötigt als Datenquelle für die Länder der Welt. Zusätzlich machen weitere Extensions wie EXT:static_info_tables_de, EXT:static_info_tables_es, usw.  Sinn, wenn man die Ländernamen auch in anderen Sprachen als englisch haben möchte.

Die php Klasse

Für ein neues Formular Element in EXT:form benötigt man eine php Klasse, die sich vor allem um das Füllen der Dropdown Optionen mit Daten kümmert, diese liegt in unserem Beispiel dann in EXT:extension/Classes/FormElements/CountryOptions.php:

 

<?php
namespace Vendor\Extension\FormElements;

use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement;
use TYPO3\CMS\Frontend\Category\Collection\CategoryCollection;

class CountryOptions extends GenericFormElement
{

    protected $valueField = '';

    protected $labelField = '';

    public function setProperty(string $key, $value)
    {
        // see form element config for the static country column to be used for the select option value
        if ($key === 'valueField') {
            $this->valueField = $value;
        }
        // see form element config for the static country column to be used for the select option label
        if ($key === 'labelField') {
            $this->labelField = $value;
            $this->setProperty('options', $this->getOptions($this->valueField, $this->labelField));
            return;
        }
        parent::setProperty($key, $value);
    }

    protected function getOptions(string $valueField, string $labelField = 'cn_short_en') : array
    {
        $options = [];
        foreach ($this->getCountries($uid) as $country) {
            $label = $country[$labelField];
            // dynamic label field generation based on current language isocode if marker {currentLanguage} is present
            if (strstr($labelField, '{currentLanguage}') !== false) {
                $siteLanguage = $GLOBALS['TYPO3_REQUEST']->getAttribute('language')->getTwoLetterIsoCode();
                if (isset($country[str_replace('{currentLanguage}', $siteLanguage, $labelField)]) && $country[str_replace('{currentLanguage}', $siteLanguage, $labelField)]) {
                    $label = $country[str_replace('{currentLanguage}', $siteLanguage, $labelField)];
                }
            }
            $options[$country[$valueField]] = $label;
        }
        asort($options);
        return $options;
    }

    protected function getCountries() : array
    {
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) ->getQueryBuilderForTable('static_countries');
        $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
        return $queryBuilder->select('*')->from('static_countries')->execute()->fetchAll();
    }

}

 

Die Element Defintion

Dann muss das Element im Form Framework angemeldet werden über folgenden YAML Code. Dieser Code kann bspw. in EXT:extension/Configuration/Form/Frontend.yaml geschrieben werden:

 

TYPO3:
  CMS:
    Form:
      prototypes:
        standard:
          formElementsDefinition:
            SingleSelectWithCountries:
              __inheritances:
                10: 'TYPO3.CMS.Form.prototypes.standard.formElementsDefinition.SingleSelect'
              implementationClassName: 'Vendor\Extension\FormElements\CountryOptions'
              renderingOptions:
                templateName: 'SingleSelect'

 

Mit dem folgenden Typoscript wird diese YAML Konfiguration dann beim Formular Framework angemeldet:

 

plugin.tx_form {
    settings {
        yamlConfigurations {
            1490817689 = EXT:extension/Configuration/Form/Frontend.yaml
        }
    }
}

 

Nutzung des Elements

Das Element selber kann man dann mit folgendem YAML Code in einem Formular nutzen. Im Neuanlage Assistent des Formular Editors im Backend ist dieses Element allerdings noch nicht für Redakteure verfügbar. Dafür müsste man noch weiteren Code schreiben.
Mit der Konfigurationsoption "valueField" kann man die Spalte der static_countries Tabelle definieren (diese Tabelle ist Teil der Extension EXT:static_info_tables), die für zu übertragenden Wert genutzt werden soll. Im folgenden Beispiel ist das der englische Landesname.
Mit der Konfigurationsoption "labelField" kann man die Spalte der static_countries Tabelle definieren, die für den anzuzeigenden Wert verwendet werden soll. Hier haben wir eine kleine Besonderheit entwickelt und zwar den Platzhalter "{currentLanguage}", welcher dann in obiger php Klasse automatisch anhand der aktuellen Sprache des Frontends mit "de", "es", usw. befüllt wird. Dafür werden dann aber für jede Sprache der Web-Site die weiteren Extensions wie EXT:static_info_tables_de, EXT:static_info_tables_es, usw. benötigt. Man kann aber auch statt dieses Markers einfach einen fixen Wert einsetzen.

 

...
      -
        properties:
          fluidAdditionalAttributes:
            required: required
          valueField: cn_short_en
          labelField: 'cn_short_{currentLanguage}'
          prependOptionLabel: 'please choose'
        defaultValue: ''
        type: SingleSelectWithCountries
        identifier: country
        label: Country
        validators:
          -
            identifier: NotEmpty
...