我下面的 TCA 在 MM 表中有很多记录,可以并排多项选择。
'select_multiplesidebyside_6' => [
'label' => 'select_multiplesidebyside_6 fieldControl',
'config' => [
'type' => 'select',
'renderType' => 'selectMultipleSideBySide',
'foreign_table' => 'tx_styleguide_staticdata',
'size' => 5,
'autoSizeMax' => 20,
'fieldControl' => [
'editPopup' => [
'disabled' => false,
'options' => [
'windowOpenParameters' => 'height=300,width=500,status=0,menubar=0,scrollbars=1',
],
],
'addRecord' => [
'disabled' => false,
],
'allSelection' => [
'renderType' => 'AllSelection'
]
],
],
],
现在,我想启用自定义选项“allSelection”来创建新按钮,单击它将从右侧选择所有可用选项并添加到选择中。
我已经添加了子类来使用classes.php覆盖NodeFactory,如下所示
<?php
return [
\TYPO3\CMS\Backend\Form\NodeFactory::class => [
'subclasses' => [
'NodeFactory' => \NK\FeatureTour\Form\NodeFactory::class
],
],
];
Xclass 如下:
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\TYPO3\CMS\Backend\Form\NodeFactory::class] = [
'className' => \NK\FeatureTour\Form\NodeFactory::class,
];
我编写了名为“AllSelection”的自定义类
<?php
declare(strict_types=1);
namespace NK\FeatureTour\Form\FieldControl;
use TYPO3\CMS\Backend\Form\AbstractNode;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
class AllSelection extends AbstractNode
{
/**
* Add button control
*
* @return array As defined by FieldControl class
*/
public function render()
{
// Logic goes here for rendering button
}
}
我的 NodeFactory 类是:
<?php
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace NK\FeatureTour\Form;
use TYPO3\CMS\Backend\Form\Container;
use TYPO3\CMS\Backend\Form\Element;
use TYPO3\CMS\Backend\Form\NodeExpansion;
use TYPO3\CMS\Backend\Form\FieldWizard;
use TYPO3\CMS\Backend\Form\FieldInformation;
use NK\FeatureTour\Form\FieldControl;
use TYPO3\CMS\Backend\Form\FieldControl as CoreFieldControl;
/**
* Create an element object depending on renderType.
*
* This is the main factory to instantiate any node within the render
* chain of FormEngine. All nodes must implement NodeInterface.
*
* Nodes are "container" classes of the render chain, "element" classes that
* render single elements, as well as "fieldWizard", "fieldInformation" and
* "fieldControl" classes which are called by single elements to enrich them.
*
* This factory gets a string "renderType" and then looks up in a list which
* specific class should handle this renderType. This list can be extended with
* own renderTypes by extensions, existing renderTypes can be overridden, and
* - for complex cases - it is possible to register own resolver classes for single
* renderTypes that can return a node class name to override the default lookup list.
*/
class NodeFactory extends \TYPO3\CMS\Backend\Form\NodeFactory
{
/**
* Default registry of node name to handling class
*
* @var array
*/
protected $nodeTypes = [
/* Default node type goes here
* Core class: \TYPO3\CMS\Backend\Form\NodeFactory
*/
...
'allSelection' => FieldControl\AllSelection::class,
...
];
/**
* Set up factory. Initialize additionally registered nodes.
*/
public function __construct()
{
parent::__construct();
}
/**
* Create a node depending on type
*
* @param array $data All information to decide which class should be instantiated and given down to sub nodes
* @return NodeInterface
* @throws Exception
*/
public function create(array $data)
{
return parent::create($data);
}
/**
* Add node types from nodeRegistry to $this->nodeTypes.
* This can be used to add new render types or to overwrite existing node types. The registered class must
* implement the NodeInterface and will be called if a node with this renderType is rendered.
*
* @throws Exception if configuration is incomplete or two nodes with identical priorities are registered
*/
protected function registerAdditionalNodeTypesFromConfiguration()
{
parent::registerAdditionalNodeTypesFromConfiguration();
}
/**
* Add resolver and add them sorted to a local property.
* This can be used to manipulate the nodeName to class resolution with own code.
*
* @throws Exception if configuration is incomplete or two resolver with identical priorities are registered
*/
protected function initializeNodeResolver()
{
parent::initializeNodeResolver();
}
/**
* Instantiate given class name
*
* @param string $className Given class name
* @param array $data Main data array
* @return object
*/
protected function instantiate($className, array $data)
{
return parent::instantiate($className, $data);
}
}
?>
但是,这在 TCA 中没有给出任何输出,任何人都可以知道如何为 selectMultipleSideBySide 添加新的自定义节点类型。
你可以尝试这个方法,
将以下内容添加到ext_localconf.php
$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1730889775]
= [
'nodeName' => 'selectAllControl',
'priority' => 40,
'class' => \Vendor\YourExt\Form\Element\SelectAllControlElement::class,
];
将以下内容添加到 TCA 中
'state' => [
'exclude' => true,
'label' => 'state',
'config' => [
'type' => 'select',
'renderType' => 'selectMultipleSideBySide',
'foreign_table' => 'your_table',
'MM' => 'your_mm_table',
'size' => 5,
'autoSizeMax' => 20,
'fieldControl' => [
'selectAllControl' => [
'disabled' => false,
'renderType' => 'selectAllControl'
],
],
],
],
添加名为“SelectAllControlElement”的节点类
<?php
namespace Vendor\YourExt\Form\Element;
use TYPO3\CMS\Backend\Form\AbstractNode;
class SelectAllControlElement extends AbstractNode
{
public function render()
{
$result = [
'iconIdentifier' => 'select-all',
'title' => 'Select All',
'linkAttributes' => [
'class' => 'importData ',
'data-id' => 'allStateSelect'
],
'requireJsModules' => ['TYPO3/CMS/YourExt/SelectAllModule'],
];
return $result;
}
}
在路径“Ext:your_ext/Resources/Public/JavaScript/SelectAllModule.js”处添加以下 Require Js
define([], function() {
document.querySelectorAll('a[data-id="allStateSelect"]').forEach(element => {
element.addEventListener('click', function() {
const selectElements = document.querySelectorAll('.form-select.t3js-formengine-select-itemstoselect');
selectElements.forEach(selectElement => {
var visibleOptions = Array.from(selectElement.options).filter(option => !option.classList.contains('hidden'));
visibleOptions.forEach(option => {
option.selected = true; // Set it as selected
selectElement.dispatchEvent(new Event('click'));
});
});
});
})
});