form input

This commit is contained in:
Benjamin Dalsass
2025-12-04 15:25:52 +01:00
parent 9c540b6227
commit 3503805fe1
20 changed files with 261 additions and 53 deletions

View File

@@ -55,7 +55,9 @@
margin-top: 24px;
}
.ibo-subform {
collection-entry-element {
margin-top: 8px;
display: block;
padding: 10px 10px;
background-color: #f5f5f5;
border-radius: 5px;

View File

@@ -18,7 +18,7 @@ class ChoicesElement extends HTMLSelectElement {
};
if (this.getAttribute('data-tom-select-disable-auto-complete')) {
options.controlInput = null;
// options.controlInput = null;
}
if (this.getAttribute('data-tom-select-max-items-selected') && this.getAttribute('data-tom-select-max-items-selected') !== '') {
options.maxItems = parseInt(this.getAttribute('data-tom-select-max-items-selected'));

View File

@@ -1,6 +1,6 @@
class CollectionElement extends HTMLElement {
#eBtn;
#eBtnAdd;
// register the custom element
static {
@@ -11,7 +11,6 @@ class CollectionElement extends HTMLElement {
const collectionHolder = document.querySelector('.'+e.currentTarget.dataset.collectionHolderClass);
const item = document.createElement('div');
item.style.marginTop = '20px';
item.innerHTML = collectionHolder
.dataset
.prototype
@@ -22,13 +21,15 @@ class CollectionElement extends HTMLElement {
collectionHolder.appendChild(item);
collectionHolder.dataset.index++;
console.log(collectionHolder.dataset.index);
}
/** connectedCallback **/
connectedCallback() {
this.#eBtn = this.querySelector('.add_item_link');
this.#eBtn.addEventListener('click', CollectionElement.addFormToCollection);
this.#eBtnAdd = this.querySelector('.add_item_link');
this.#eBtnAdd.addEventListener('click', CollectionElement.addFormToCollection);
}
#removeCollectionItem() {
}
}

View File

@@ -0,0 +1,19 @@
class CollectionEntryElement extends HTMLElement {
#eBtnDelete;
// register the custom element
static {
customElements.define('collection-entry-element', CollectionEntryElement);
}
/** connectedCallback **/
connectedCallback() {
this.#eBtnDelete = this.querySelector('.remove_item_link');
this.#eBtnDelete.addEventListener('click', this.#removeCollectionItem.bind(this));
}
#removeCollectionItem(e) {
this.remove();
}
}

View File

@@ -491,6 +491,7 @@ return array(
'Combodo\\iTop\\Forms\\Block\\Base\\TextAreaFormBlock' => $baseDir . '/sources/Forms/Block/Base/TextAreaFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\Base\\TextFormBlock' => $baseDir . '/sources/Forms/Block/Base/TextFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeChoiceFormBlock' => $baseDir . '/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeTypeChoiceFormBlock' => $baseDir . '/sources/Forms/Block/DataModel/AttributeTypeChoiceFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeValueChoiceFormBlock' => $baseDir . '/sources/Forms/Block/DataModel/AttributeValueChoiceFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\DataModel\\LabelFormBlock' => $baseDir . '/sources/Forms/Block/DataModel/LabelFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\DataModel\\OqlFormBlock' => $baseDir . '/sources/Forms/Block/DataModel/OqlFormBlock.php',
@@ -525,6 +526,8 @@ return array(
'Combodo\\iTop\\Forms\\IO\\FormOutput' => $baseDir . '/sources/Forms/IO/FormOutput.php',
'Combodo\\iTop\\Forms\\IO\\Format\\AbstractIOFormat' => $baseDir . '/sources/Forms/IO/Format/AbstractIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\AttributeIOFormat' => $baseDir . '/sources/Forms/IO/Format/AttributeIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\AttributeTypeArrayIOFormat' => $baseDir . '/sources/Forms/IO/Format/AttributeTypeArrayIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\AttributeTypeIOFormat' => $baseDir . '/sources/Forms/IO/Format/AttributeTypeIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\BooleanIOFormat' => $baseDir . '/sources/Forms/IO/Format/BooleanIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\ClassIOFormat' => $baseDir . '/sources/Forms/IO/Format/ClassIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\NumberIOFormat' => $baseDir . '/sources/Forms/IO/Format/NumberIOFormat.php',
@@ -3894,5 +3897,5 @@ return array(
'privUITransactionFile' => $baseDir . '/application/transaction.class.inc.php',
'privUITransactionSession' => $baseDir . '/application/transaction.class.inc.php',
'utils' => $baseDir . '/application/utils.inc.php',
'<EFBFBD>' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php',
'©' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php',
);

View File

@@ -877,6 +877,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Combodo\\iTop\\Forms\\Block\\Base\\TextAreaFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/TextAreaFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\Base\\TextFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/TextFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeChoiceFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeTypeChoiceFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/DataModel/AttributeTypeChoiceFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeValueChoiceFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/DataModel/AttributeValueChoiceFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\DataModel\\LabelFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/DataModel/LabelFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\DataModel\\OqlFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/DataModel/OqlFormBlock.php',
@@ -911,6 +912,8 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Combodo\\iTop\\Forms\\IO\\FormOutput' => __DIR__ . '/../..' . '/sources/Forms/IO/FormOutput.php',
'Combodo\\iTop\\Forms\\IO\\Format\\AbstractIOFormat' => __DIR__ . '/../..' . '/sources/Forms/IO/Format/AbstractIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\AttributeIOFormat' => __DIR__ . '/../..' . '/sources/Forms/IO/Format/AttributeIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\AttributeTypeArrayIOFormat' => __DIR__ . '/../..' . '/sources/Forms/IO/Format/AttributeTypeArrayIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\AttributeTypeIOFormat' => __DIR__ . '/../..' . '/sources/Forms/IO/Format/AttributeTypeIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\BooleanIOFormat' => __DIR__ . '/../..' . '/sources/Forms/IO/Format/BooleanIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\ClassIOFormat' => __DIR__ . '/../..' . '/sources/Forms/IO/Format/ClassIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\NumberIOFormat' => __DIR__ . '/../..' . '/sources/Forms/IO/Format/NumberIOFormat.php',
@@ -4280,7 +4283,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'privUITransactionFile' => __DIR__ . '/../..' . '/application/transaction.class.inc.php',
'privUITransactionSession' => __DIR__ . '/../..' . '/application/transaction.class.inc.php',
'utils' => __DIR__ . '/../..' . '/application/utils.inc.php',
'<EFBFBD>' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php',
'©' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php',
);
public static function getInitializer(ClassLoader $loader)

View File

@@ -185,6 +185,7 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
$this->LinkScriptFromAppRoot('js/forms/custom-elements/choices.js');
$this->LinkScriptFromAppRoot('js/forms/custom-elements/oql.js');
$this->LinkScriptFromAppRoot('js/forms/custom-elements/collection.js');
$this->LinkScriptFromAppRoot('js/forms/custom-elements/collection_entry.js');
// Used by inline image, CKEditor and other places
$this->LinkScriptFromAppRoot('node_modules/magnific-popup/dist/jquery.magnific-popup.min.js');

View File

@@ -43,14 +43,15 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function __construct(private readonly string $sName, array $aOptions = [])
{
// Register IO
$this->RegisterIO($this->oIORegister = new IORegister($this));
$this->AfterIORegistered($this->oIORegister);
// Register options
$this->RegisterOptions($this->oOptionsRegister = new OptionsRegister());
$this->SetOptions($aOptions);
$this->AfterOptionsRegistered($this->oOptionsRegister);
// Register IO
$this->RegisterIO($this->oIORegister = new IORegister($this));
$this->AfterIORegistered($this->oIORegister);
}
/**
@@ -307,9 +308,25 @@ abstract class AbstractFormBlock implements IFormBlock
* @return $this
* @throws FormBlockException
*/
public function DependsOn(string $sInputName, string $sOutputBlockName, string $sOutputName): AbstractFormBlock
public function InputDependsOn(string $sInputName, string $sOutputBlockName, string $sOutputName): AbstractFormBlock
{
$this->oIORegister->DependsOn($sInputName, $sOutputBlockName, $sOutputName);
$this->oIORegister->InputDependsOn($sInputName, $sOutputBlockName, $sOutputName);
return $this;
}
/**
* Set an input value.
*
* @param string $sInputName
* @param mixed $oValue
*
* @return $this
* @throws RegisterException
*/
public function SetInputValue(string $sInputName, mixed $oValue): AbstractFormBlock
{
$this->oIORegister->GetInput($sInputName)->SetValue(AbstractFormIO::EVENT_FORM_STATIC, $oValue);
return $this;
}
@@ -322,9 +339,9 @@ abstract class AbstractFormBlock implements IFormBlock
* @return $this
* @throws FormBlockException
*/
public function DependsOnParent(string $sInputName, string $sParentInputName): AbstractFormBlock
public function InputDependsOnParent(string $sInputName, string $sParentInputName): AbstractFormBlock
{
$this->oIORegister->DependsOnParent($sInputName, $sParentInputName);
$this->oIORegister->InputDependsOnParent($sInputName, $sParentInputName);
return $this;
}
@@ -337,9 +354,9 @@ abstract class AbstractFormBlock implements IFormBlock
* @return $this
* @throws FormBlockException
*/
public function ImpactParent(string $sOutputName, string $sParentOutputName): AbstractFormBlock
public function OutputImpactParent(string $sOutputName, string $sParentOutputName): AbstractFormBlock
{
$this->oIORegister->ImpactParent($sOutputName, $sParentOutputName);
$this->oIORegister->OutputImpactParent($sOutputName, $sParentOutputName);
return $this;
}

View File

@@ -36,7 +36,7 @@ class CollectionBlock extends AbstractTypeFormBlock
public function EntryDependsOnParent(string $sInputName, string $sParentInputName): AbstractFormBlock
{
$this->oPrototypeBlock->DependsOnParent($sInputName, $sParentInputName);
$this->oPrototypeBlock->InputDependsOnParent($sInputName, $sParentInputName);
return $this;
}

View File

@@ -7,7 +7,10 @@
namespace Combodo\iTop\Forms\Block\DataModel;
use Combodo\iTop\Core\AttributeDefinition\AttributeEnum;
use Combodo\iTop\Forms\Block\FormBlockException;
use Combodo\iTop\Forms\IO\Format\AttributeTypeArrayIOFormat;
use Combodo\iTop\Forms\IO\Format\AttributeTypeIOFormat;
use Combodo\iTop\Forms\Register\RegisterException;
use Combodo\iTop\Service\DependencyInjection\DIException;
use Combodo\iTop\Service\DependencyInjection\DIService;
@@ -29,6 +32,7 @@ class AttributeChoiceFormBlock extends ChoiceFormBlock
{
// inputs
public const INPUT_CLASS_NAME = 'input_class_name';
public const INPUT_ATTRIBUTE_TYPE = 'input_attribute_type';
// outputs
public const OUTPUT_ATTRIBUTE = 'output_attribute';
@@ -46,6 +50,7 @@ class AttributeChoiceFormBlock extends ChoiceFormBlock
{
parent::RegisterIO($oIORegister);
$oIORegister->AddInput(self::INPUT_CLASS_NAME, ClassIOFormat::class);
$oIORegister->AddInput(self::INPUT_ATTRIBUTE_TYPE, AttributeTypeIOFormat::class);
$oIORegister->AddOutput(self::OUTPUT_ATTRIBUTE, AttributeIOFormat::class);
}
@@ -62,6 +67,7 @@ class AttributeChoiceFormBlock extends ChoiceFormBlock
// Get class name
$sClass = strval($this->GetInputValue(self::INPUT_CLASS_NAME));
$sAttType = $this->GetInputValue(self::INPUT_ATTRIBUTE_TYPE)->sAttributeType;
// Empty class => no choices
if (utils::IsNullOrEmptyString($sClass)) {
@@ -71,7 +77,7 @@ class AttributeChoiceFormBlock extends ChoiceFormBlock
/** List attributes @var ModelReflection $oModelReflection */
$oModelReflection = DIService::GetInstance()->GetService('ModelReflection');
$aAttributeCodes = array_keys($oModelReflection->ListAttributes($sClass));
$aAttributeCodes = array_keys($oModelReflection->ListAttributes($sClass, $sAttType));
$aAttributes = [];
foreach ($aAttributeCodes as $sAttCode) {
$sLabel = $oModelReflection->GetLabel($sClass, $sAttCode);

View File

@@ -0,0 +1,53 @@
<?php
/*
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\DataModel;
use AttributeClass;
use Combodo\iTop\Core\AttributeDefinition\AttributeBoolean;
use Combodo\iTop\Core\AttributeDefinition\AttributeDate;
use Combodo\iTop\Core\AttributeDefinition\AttributeEnum;
use Combodo\iTop\Core\AttributeDefinition\AttributeString;
use Combodo\iTop\Forms\IO\Format\AttributeTypeIOFormat;
use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock;
use Combodo\iTop\Forms\Register\IORegister;
use Combodo\iTop\Forms\Register\OptionsRegister;
/**
* A block to choose an attribute type.
*
* @package Combodo\iTop\Forms\Block\DataModel
* @since 3.3.0
*/
class AttributeTypeChoiceFormBlock extends ChoiceFormBlock
{
// outputs
public const OUTPUT_ATTRIBUTE_TYPE = 'output_type';
/** @inheritdoc */
protected function RegisterOptions(OptionsRegister $oOptionsRegister): void
{
parent::RegisterOptions($oOptionsRegister);
$oOptionsRegister->SetOption('placeholder', 'Select a type...');
$oOptionsRegister->SetOption('choices', [
'enum' => AttributeEnum::class,
'string' => AttributeString::class,
'date' => AttributeDate::class,
'boolean' => AttributeBoolean::class,
'class' => AttributeClass::class,
]);
}
/** @inheritdoc */
protected function RegisterIO(IORegister $oIORegister): void
{
parent::RegisterIO($oIORegister);
$oIORegister->AddOutput(self::OUTPUT_ATTRIBUTE_TYPE, AttributeTypeIOFormat::class);
}
}

View File

@@ -7,7 +7,9 @@
namespace Combodo\iTop\Forms\FormType;
use Combodo\iTop\Forms\Block\AbstractFormBlock;
use Combodo\iTop\Forms\Block\Base\FormBlock;
use Combodo\iTop\Forms\FormBuilder\DependencyMap;
use Symfony\Component\Form\FormInterface;
/**
@@ -57,7 +59,7 @@ class FormTypeHelper
$oMap = $oBlockTurboTrigger->GetParent()->GetDependenciesMap();
// Add impacted blocks
$aImpacted = $oMap->GetBlocksImpactedBy($oBlockTurboTrigger->GetName());
$aImpacted = static::GetImpactedByRecursive($oMap, $oBlockTurboTrigger);
foreach ($aImpacted as $oImpactedBlock) {
$sName = $sParentName.'_'.$oImpactedBlock->GetName();
if ($oParent->has($oImpactedBlock->GetName())) {
@@ -74,6 +76,21 @@ class FormTypeHelper
];
}
private static function GetImpactedByRecursive(DependencyMap $oMap, AbstractFormBlock $oBLock): ?array
{
$aImpacted = $oMap->GetBlocksImpactedBy($oBLock->GetName());
if ($aImpacted !== null) {
foreach ($aImpacted as $oImpactedBlock) {
$aRecursiveImpacted = static::GetImpactedByRecursive($oMap, $oImpactedBlock);
if ($aRecursiveImpacted !== null) {
$aImpacted = array_merge($aImpacted, $aRecursiveImpacted);
}
}
}
return $aImpacted;
}
/**
* @param FormInterface $oForm
* @param string $sBlockTurboTriggerName

View File

@@ -19,6 +19,10 @@ use Symfony\Component\Form\FormEvents;
*/
class AbstractFormIO
{
public const EVENT_POST_SET_DATA = FormEvents::POST_SET_DATA;
public const EVENT_POST_SUBMIT = FormEvents::POST_SUBMIT;
public const EVENT_FORM_STATIC = 'form.static';
/** @var AbstractFormBlock The owner block */
private AbstractFormBlock $oOwnerBlock;
@@ -43,7 +47,7 @@ class AbstractFormIO
* @param string $sName name of the IO
* @param string $sType type of the IO
*
* @throws \Combodo\iTop\Forms\IO\FormBlockIOException
* @throws FormBlockIOException
*/
public function __construct(string $sName, string $sType, AbstractFormBlock $oOwnerBlock)
{
@@ -81,7 +85,7 @@ class AbstractFormIO
* @param string $sName
*
* @return self
* @throws \Combodo\iTop\Forms\IO\FormBlockIOException
* @throws FormBlockIOException
*/
public function SetName(string $sName): self
{
@@ -204,6 +208,9 @@ class AbstractFormIO
*/
private function Value(): mixed
{
if (array_key_exists('form.static', $this->aValues)) {
return $this->aValues['form.static'];
}
if (array_key_exists(FormEvents::POST_SUBMIT, $this->aValues)) {
return $this->aValues[FormEvents::POST_SUBMIT];
}
@@ -220,7 +227,7 @@ class AbstractFormIO
* @param FormInput $oDestinationIO
*
* @return FormBinding
* @throws \Combodo\iTop\Forms\IO\FormBlockIOException
* @throws FormBlockIOException
*/
public function BindToInput(FormInput $oDestinationIO): FormBinding
{
@@ -236,7 +243,7 @@ class AbstractFormIO
* @param FormBinding $oFormBinding
*
* @return void
* @throws \Combodo\iTop\Forms\IO\FormBlockIOException when already bound
* @throws FormBlockIOException when already bound
*/
public function Attach(FormBinding $oFormBinding): void
{

View File

@@ -29,7 +29,10 @@ class FormOutput extends AbstractFormIO
*
* @param string $sName
* @param string $sType
* @param AbstractFormBlock $oOwnerBlock
* @param AbstractConverter|null $oConverter
*
* @throws FormBlockIOException
*/
public function __construct(string $sName, string $sType, AbstractFormBlock $oOwnerBlock, AbstractConverter $oConverter = null)
{
@@ -91,7 +94,7 @@ class FormOutput extends AbstractFormIO
* @param FormOutput $oDestinationIO
*
* @return FormBinding
* @throws \Combodo\iTop\Forms\IO\FormBlockIOException
* @throws FormBlockIOException
*/
public function BindToOutput(FormOutput $oDestinationIO): FormBinding
{

View File

@@ -0,0 +1,34 @@
<?php
namespace Combodo\iTop\Forms\IO\Format;
use Combodo\iTop\Service\DependencyInjection\DIService;
use Combodo\iTop\Forms\IO\FormBlockIOException;
/**
* Attribute type array IO format.
*
* @package Combodo\iTop\Forms\IO\Format
* @since 3.3.0
*/
class AttributeTypeArrayIOFormat extends AbstractIOFormat
{
public array $aClasses;
/**
*/
public function __construct(array $aClasses)
{
$this->aClasses = $aClasses;
}
public function __toString(): string
{
return json_encode($this->aClasses);
}
public function jsonSerialize(): mixed
{
return json_encode($this->aClasses);
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace Combodo\iTop\Forms\IO\Format;
/**
* Attribute type IO format.
*
* @package Combodo\iTop\Forms\IO\Format
* @since 3.3.0
*/
class AttributeTypeIOFormat extends AbstractIOFormat
{
public string $sAttributeType;
public function __construct(string $sAttributeType)
{
$this->sAttributeType = $sAttributeType;
}
public function __toString(): string
{
return $this->sAttributeType;
}
public function jsonSerialize(): mixed
{
return $this->sAttributeType;
}
}

View File

@@ -74,7 +74,7 @@ class IORegister
$oBlockOutput = $oOutputBlock->GetOutput($sOutputName);
$this->AddInput($sName, $oBlockOutput->GetDataType());
$this->DependsOn($sName, $sOutputBlockName, $sOutputName);
$this->InputDependsOn($sName, $sOutputBlockName, $sOutputName);
return $this;
}
@@ -91,7 +91,7 @@ class IORegister
* @throws FormBlockIOException
* @throws RegisterException
*/
public function DependsOn(string $sInputName, string $sOutputBlockName, string $sOutputName): self
public function InputDependsOn(string $sInputName, string $sOutputBlockName, string $sOutputName): self
{
$oOutputBlock = $this->oFormBlock->GetParent()?->Get($sOutputBlockName);
if (is_null($oOutputBlock)) {
@@ -115,7 +115,7 @@ class IORegister
* @throws FormBlockIOException
* @throws RegisterException
*/
public function ImpactParent(string $sOutputName, string $sParentOutputName): self
public function OutputImpactParent(string $sOutputName, string $sParentOutputName): self
{
$oFormOutput = $this->GetOutput($sOutputName);
$oParentFormOutput = $this->oFormBlock->GetParent()->GetOutput($sParentOutputName);
@@ -359,7 +359,7 @@ class IORegister
* @throws FormBlockIOException
* @throws RegisterException
*/
public function DependsOnParent(string $sInputName, string $sParentInputName): self
public function InputDependsOnParent(string $sInputName, string $sParentInputName): self
{
$oFormInput = $this->GetInput($sInputName);
$oParentFormInput = $this->oFormBlock->GetParent()->GetInput($sParentInputName);

View File

@@ -23,7 +23,7 @@
{%- block choice_widget_collapsed -%}
{% set attr = attr|merge({class: (attr.class|default('') ~ ' ibo-input')|trim}) %}
<select is="choices-element" class="field_autocomplete ibo-input ibo-input-select ibo-input-select-autocomplete ui-autocomplete-input" style="display: none"
<select is="choices-element" class="field_autocomplete ibo-input ibo-input-select ibo-input-select-autocomplete ui-autocomplete-input"
{{ block('widget_attributes') }}
{% if multiple %} multiple="multiple" {% endif %}
{% if max_items_selected is defined %} data-tom-select-max-items-selected="{{ max_items_selected }}" {% endif %}
@@ -79,16 +79,30 @@
{%- endblock form_rows -%}
{%- block collection_widget -%}
<collection-element>
{% if prototype is defined and not prototype.rendered %}
{%- set attr = attr|merge({'data-prototype': form_row(prototype), 'class': name, 'data-index': form|length > 0 ? form|last.vars.name + 1 : 0 }) -%}
{% endif %}
{{- block('form_widget') -}}
{% if allow_add %}
<div style="margin-top: 20px;">
<button type="button" class="add_item_link ibo-button ibo-button ibo-is-regular " data-collection-holder-class="{{ name }}">{{ button_label|dict_s }}</button>
</div>
{% set deleteBtn = '<button type="button" class="remove_item_link ibo-button ibo-is-regular ibo-is-danger">Supprimer</button>' %}
{%- set prototype_html = '<collection-entry-element>' ~ form_widget(prototype) ~ ' ' ~ deleteBtn ~'</collection-entry-element>' -%}
{%- set attr = attr|merge({'data-prototype': prototype_html, 'class': name, 'data-index': form|length > 0 ? form|last.vars.name + 1 : 0 }) -%}
{% endif %}
<collection-element {{ block('widget_container_attributes') }}>
{% for child in form %}
<collection-entry-element>
{{ form_widget(child) }}
{% if allow_delete %}
<button type="button" class="remove_item_link ibo-button ibo-is-regular ibo-is-danger">Supprimer</button>
{% endif %}
</collection-entry-element>
{% endfor %}
{% if allow_add %}
<div style="margin-top: 20px;">
<button type="button" class="add_item_link ibo-button ibo-button ibo-is-regular " data-collection-holder-class="{{ name }}">{{ button_label|dict_s }}</button>
</div>
{% endif %}
</collection-element>
{%- endblock collection_widget -%}
@@ -130,4 +144,3 @@
</button>
</div>
{%- endblock oql_form_row -%}

View File

@@ -80,7 +80,7 @@ class BlockTest extends AbstractFormsTest
$oFormBlock = new FormBlock('formBlock');
$oFormBlock->Add('allow_age', CheckboxFormBlock::class, []);
$oBirthdateBlock = $oFormBlock->Add('birthdate', TextFormBlock::class, [])
->DependsOn(AbstractTypeFormBlock::INPUT_VISIBLE, 'allow_age', CheckboxFormBlock::OUTPUT_CHECKED);
->InputDependsOn(AbstractTypeFormBlock::INPUT_VISIBLE, 'allow_age', CheckboxFormBlock::OUTPUT_CHECKED);
$this->assertTrue($oBirthdateBlock->HasDependenciesBlocks());
}
@@ -100,7 +100,7 @@ class BlockTest extends AbstractFormsTest
$oFormBlock->Add('lastname', TextFormBlock::class, []);
$oFormBlock->Add('allow_age', CheckboxFormBlock::class, []);
$oFormBlock->Add('birthdate', TextFormBlock::class, [])
->DependsOn(AbstractTypeFormBlock::INPUT_VISIBLE, 'allow_age', CheckboxFormBlock::OUTPUT_CHECKED);
->InputDependsOn(AbstractTypeFormBlock::INPUT_VISIBLE, 'allow_age', CheckboxFormBlock::OUTPUT_CHECKED);
// form builder
$oFormFactoryBuilder = Forms::createFormFactoryBuilder();

View File

@@ -81,9 +81,9 @@ class IORegisterTest extends AbstractFormsTest
$oSubForm->AddInput('input_from_C', StringIOFormat::class);
$oSubForm->AddInput('unbound_input', StringIOFormat::class);
$this->GivenIORegister($oSubForm)->DependsOn('input_from_A', 'SubFormA', TextFormBlock::OUTPUT_TEXT);
$this->GivenIORegister($oSubForm)->DependsOn('input_from_B', 'SubFormB', CheckboxFormBlock::OUTPUT_CHECKED);
$this->GivenIORegister($oSubForm)->DependsOn('input_from_C', 'SubFormC', TextFormBlock::OUTPUT_TEXT);
$this->GivenIORegister($oSubForm)->InputDependsOn('input_from_A', 'SubFormA', TextFormBlock::OUTPUT_TEXT);
$this->GivenIORegister($oSubForm)->InputDependsOn('input_from_B', 'SubFormB', CheckboxFormBlock::OUTPUT_CHECKED);
$this->GivenIORegister($oSubForm)->InputDependsOn('input_from_C', 'SubFormC', TextFormBlock::OUTPUT_TEXT);
$aBoundInputs = $this->GivenIORegister($oSubForm)->GetBoundInputs();
$this->assertCount(3, $aBoundInputs);
@@ -96,7 +96,7 @@ class IORegisterTest extends AbstractFormsTest
$oSubFormA = $this->GivenSubFormBlock($this->oFormBlock, 'SubFormA', TextFormBlock::class);
$oIORegisterA = $this->GivenIORegister($oSubFormA);
$oIORegisterA->ImpactParent(TextFormBlock::OUTPUT_TEXT, 'output');
$oIORegisterA->OutputImpactParent(TextFormBlock::OUTPUT_TEXT, 'output');
$this->assertCount(1, $this->oIORegister->GetBoundOutputs());
}
@@ -119,7 +119,7 @@ class IORegisterTest extends AbstractFormsTest
$oSubFormA = $this->GivenSubFormBlock($this->oFormBlock, 'SubFormA', TextFormBlock::class);
$oIORegisterA = $this->GivenIORegister($oSubFormA);
$oIORegisterA->ImpactParent(TextFormBlock::OUTPUT_TEXT, 'output');
$oIORegisterA->OutputImpactParent(TextFormBlock::OUTPUT_TEXT, 'output');
$this->assertTrue($this->oFormBlock->GetOutput('output')->IsBound());
}
@@ -145,7 +145,7 @@ class IORegisterTest extends AbstractFormsTest
$this->expectException(RegisterException::class);
$this->oIORegister->DependsOn('non_existing_input', 'OtherBlock', 'test_output');
$this->oIORegister->InputDependsOn('non_existing_input', 'OtherBlock', 'test_output');
}
public function testDependingOnNonExistingOutputThrowsException(): void
@@ -153,7 +153,7 @@ class IORegisterTest extends AbstractFormsTest
$this->oIORegister->AddInput('test_input', StringIOFormat::class);
$this->expectException(RegisterException::class);
$this->oIORegister->DependsOn('test_input', 'OtherBlock', 'non_existing_output');
$this->oIORegister->InputDependsOn('test_input', 'OtherBlock', 'non_existing_output');
}
public function testDependingOnNonExistingBlockThrowsException(): void
@@ -162,7 +162,7 @@ class IORegisterTest extends AbstractFormsTest
$this->oIORegister->AddOutput('test_output', StringIOFormat::class);
$this->expectException(RegisterException::class);
$this->oIORegister->DependsOn('test_input', 'UnknownBlock', 'test');
$this->oIORegister->InputDependsOn('test_input', 'UnknownBlock', 'test');
}
public function testHasDependenciesBlocks(): void
@@ -172,7 +172,7 @@ class IORegisterTest extends AbstractFormsTest
$oSubForm = $this->GivenSubFormBlock($this->oFormBlock, 'SubForm', TextFormBlock::class);
$oSubForm->AddInput('input_from_A', StringIOFormat::class);
$this->GivenIORegister($oSubForm)->DependsOn('input_from_A', 'SubFormA', TextFormBlock::OUTPUT_TEXT);
$this->GivenIORegister($oSubForm)->InputDependsOn('input_from_A', 'SubFormA', TextFormBlock::OUTPUT_TEXT);
$this->assertTrue($this->GivenIORegister($oSubForm)->HasDependenciesBlocks());
$this->assertFalse($this->oIORegister->HasDependenciesBlocks());
@@ -185,7 +185,7 @@ class IORegisterTest extends AbstractFormsTest
$oSubForm = $this->GivenSubFormBlock($this->oFormBlock, 'SubForm', TextFormBlock::class);
$oSubForm->AddInput('input_from_A', StringIOFormat::class);
$this->GivenIORegister($oSubForm)->DependsOn('input_from_A', 'SubFormA', TextFormBlock::OUTPUT_TEXT);
$this->GivenIORegister($oSubForm)->InputDependsOn('input_from_A', 'SubFormA', TextFormBlock::OUTPUT_TEXT);
$this->assertFalse($this->GivenIORegister($oSubForm)->ImpactDependentsBlocks());
$this->assertTrue($this->GivenIORegister($oSubFormA)->ImpactDependentsBlocks());