N°8772 - dynamic form

This commit is contained in:
Benjamin Dalsass
2025-11-03 13:50:07 +01:00
parent 68d2038488
commit 20da9664c2
5 changed files with 82 additions and 32 deletions

View File

@@ -418,13 +418,8 @@ abstract class AbstractFormBlock implements IFormBlock
/** Iterate throw output @var FormOutput $oFormOutput */
foreach ($this->aFormOutputs as $oFormOutput) {
try {
// Compute the output value
$oFormOutput->ComputeValue($sEventType, $oData);
}
catch (IOException $oException) {
IssueLog::Exception(sprintf('Unable to compute values for output %s of block %s', $oFormOutput->GetName(), $this->GetName()), $oException);
}
// Compute the output value
$oFormOutput->ComputeValue($sEventType, $oData);
}
}

View File

@@ -13,6 +13,9 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
*
@@ -26,6 +29,21 @@ class ChoiceFormType extends AbstractType
}
/** @inheritdoc */
public function configureOptions(OptionsResolver $resolver): void
{
parent::configureOptions($resolver);
$resolver->setDefault('inline_display', true);
}
public function buildView(FormView $view, FormInterface $form, array $options): void
{
parent::buildView($view, $form, $options);
$view->vars['inline_display'] = $options['inline_display'];
}
/** @inheritdoc */
public function buildForm(FormBuilderInterface $builder, array $options): void
{
// on preset data

View File

@@ -7,7 +7,9 @@
namespace Combodo\iTop\Forms\FormBuilder;
use Combodo\iTop\Forms\Block\AbstractFormBlock;
use Exception;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
@@ -131,7 +133,12 @@ class DependencyHandler
$oFormBlock = $this->aSubBlocks[$oForm->getName()];
// Compute the block outputs with the data
$oFormBlock->ComputeOutputs($sEventType, $oForm->getData());
try{
$oFormBlock->ComputeOutputs($sEventType, $oForm->getData());
}
catch(Exception $e){
$oForm->addError(new FormError($e->getMessage()));
}
// Check dependencies
$this->CheckDependencies($oForm->getParent(), $oForm->getName(), $sEventType);

View File

@@ -26,27 +26,37 @@
{{- parent() -}}
{%- endblock choice_widget_collapsed -%}
{%- block choice_widget_expanded -%}
<div {{ block('widget_container_attributes') }}>
{%- for child in form %}
{{- form_widget(child) -}}
{{- form_label(child, null, {translation_domain: choice_translation_domain, no_label_class: true}) -}}
{% endfor -%}
</div>
{%- endblock choice_widget_expanded -%}
{%- block form_label -%}
{%- if compound is defined and compound -%}
{%- set no_legend_element = inline_display is defined and inline_display -%}
{%- if compound is defined and compound and not no_legend_element -%}
{%- set element = 'legend' -%}
{%- else -%}
{%- elseif no_label_class is not defined or not no_label_class -%}
{% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ibo-field--label')|trim}) %}
{%- endif -%}
{{- parent() -}}
{%- endblock form_label -%}
{#{%- block form_rows -%}#}
{%- block form_rows -%}
{# {% for block in blocks %}#}
{# <div id="block_{{ block.name }}" class="ibo-field ibo-content-block ibo-block ibo-field-small">#}
{# {{ block.name }} {{ block.added }}#}
{# {% if block.added == 1 %}#}
{# {{ form_row(form[block.name]) }}#}
{# {% endif %}#}
{# </div>#}
{# {% endfor %}#}
{% for block in blocks %}
<div id="block_{{ block.name }}" class="ibo-field ibo-content-block ibo-block ibo-field-small">
{{ block.name }} {{ block.added }}
{% if block.added == 1 %}
{{ form_row(form[block.name]) }}
{% endif %}
</div>
{% endfor %}
{#{%- endblock form_rows -%}#}
{%- endblock form_rows -%}
{%- block collection_widget -%}
{% if prototype is defined and not prototype.rendered %}

View File

@@ -21,22 +21,26 @@ use ReflectionException;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
/**
* Test forms block.
*
*/
class Block extends ItopDataTestCase
{
/**
* Block get form type must return a class derived from Symfony form AbstractType.
*
* @throws ReflectionException
*/
public function testBlockFormType()
public function testFormBlockProvideSymfonyFormType(): void
{
$oChoiceBlock = new ChoiceFormBlock('choiceBlock');
$test = new \ReflectionClass($oChoiceBlock->GetFormType());
$this->assertTrue($test->isSubclassOf(AbstractType::class));
$oFormBlock = new ChoiceFormBlock('formBlock');
$test = new \ReflectionClass($oFormBlock->GetFormType());
$this->assertTrue($test->isSubclassOf(AbstractType::class));
$aFormBlocks = InterfaceDiscovery::GetInstance()->FindItopClasses(iFormBlock::class);
foreach ($aFormBlocks as $sFormBlock) {
$oChoiceBlock = new($sFormBlock)($sFormBlock);
$oClass = new \ReflectionClass($oChoiceBlock->GetFormType());
$this->assertTrue($oClass->isSubclassOf(AbstractType::class));
}
}
/**
@@ -44,7 +48,7 @@ class Block extends ItopDataTestCase
*
* @throws ReflectionException
*/
public function testAddBlockFromSymfonyType()
public function testAddBlockFromSymfonyType(): void
{
$oFormBlock = new FormBlock('formBlock');
$this->expectException(FormBlockException::class);
@@ -54,14 +58,30 @@ class Block extends ItopDataTestCase
/**
* All block may contain a reference to themselves in their options
*/
public function testBlockOptionsContainsBlockReference()
public function testBlockOptionsContainsBlockReference(): void
{
$aFormBlocks = InterfaceDiscovery::GetInstance()->FindItopClasses(iFormBlock::class);
foreach ($aFormBlocks as $sFormBlock) {
$oChoiceBlock = new($sFormBlock)($sFormBlock);
$this->assertTrue($oChoiceBlock->GetOptions()['form_block'] === $oChoiceBlock);
}
}
/**
* Check that a block with dependencies return true for HasDependenciesBlocks.
*
* @return void
* @throws FormBlockException
* @throws ReflectionException
*/
public function testCheckDependencyState(): void
{
$oFormBlock = new FormBlock('formBlock');
$oFormBlock->Add('allow_age', CheckboxFormBlock::class, []);
$oBirthdateBlock = $oFormBlock->Add('birthdate', TextFormBlock::class, [])
->DependsOn(AbstractFormBlock::INPUT_VISIBLE, 'allow_age', CheckboxFormBlock::OUTPUT_CHECKED);
$this->assertTrue($oBirthdateBlock->HasDependenciesBlocks());
}
/**
@@ -71,7 +91,7 @@ class Block extends ItopDataTestCase
* @throws FormBlockException
* @throws ReflectionException
*/
public function testFormBlockNotContainsDependentFields()
public function testFormBlockNotContainsDependentFields(): void
{
// form with a dependent field
$oFormBlock = new FormBlock('formBlock');