merged branch bschussek/issue4615 (PR #4799)
Commits
-------
df5bb4a
[Form] Unified rendering of errors for nested elements
Discussion
----------
[Form] Unified rendering of errors for nested elements
Bug fix: yes
Feature addition: no
Backwards compatibility break: yes?
Symfony2 tests pass: yes
Fixes the following tickets: #4615
Todo: -
This commit is contained in:
commit
2cf1a0a7e8
@ -20,6 +20,9 @@
|
|||||||
{% block form_widget_compound %}
|
{% block form_widget_compound %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
<div {{ block('widget_container_attributes') }}>
|
<div {{ block('widget_container_attributes') }}>
|
||||||
|
{% if form.parent is empty %}
|
||||||
|
{{ form_errors(form) }}
|
||||||
|
{% endif %}
|
||||||
{{ block('form_rows') }}
|
{{ block('form_rows') }}
|
||||||
{{ form_rest(form) }}
|
{{ form_rest(form) }}
|
||||||
</div>
|
</div>
|
||||||
@ -236,6 +239,10 @@
|
|||||||
|
|
||||||
{% block repeated_row %}
|
{% block repeated_row %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
|
{#
|
||||||
|
No need to render the errors here, as all errors are mapped
|
||||||
|
to the first child (see RepeatedTypeValidatorExtension).
|
||||||
|
#}
|
||||||
{{ block('form_rows') }}
|
{{ block('form_rows') }}
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock repeated_row %}
|
{% endblock repeated_row %}
|
||||||
@ -244,13 +251,7 @@
|
|||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
<div>
|
<div>
|
||||||
{{ form_label(form, label|default(null)) }}
|
{{ form_label(form, label|default(null)) }}
|
||||||
{#
|
{{ form_errors(form) }}
|
||||||
If the child is a compound form, the errors are rendered inside
|
|
||||||
the container. See also block form_rows.
|
|
||||||
#}
|
|
||||||
{% if not compound %}
|
|
||||||
{{ form_errors(form) }}
|
|
||||||
{% endif %}
|
|
||||||
{{ form_widget(form) }}
|
{{ form_widget(form) }}
|
||||||
</div>
|
</div>
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
@ -298,7 +299,6 @@
|
|||||||
|
|
||||||
{% block form_rows %}
|
{% block form_rows %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
{{ form_errors(form) }}
|
|
||||||
{% for child in form %}
|
{% for child in form %}
|
||||||
{{ form_row(child) }}
|
{{ form_row(child) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -7,31 +7,13 @@
|
|||||||
{{ form_label(form, label|default(null)) }}
|
{{ form_label(form, label|default(null)) }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% if not compound %}
|
{{ form_errors(form) }}
|
||||||
{{ form_errors(form) }}
|
|
||||||
{% endif %}
|
|
||||||
{{ form_widget(form) }}
|
{{ form_widget(form) }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endblock form_row %}
|
{% endblock form_row %}
|
||||||
|
|
||||||
{% block form_errors %}
|
|
||||||
{% spaceless %}
|
|
||||||
{% if not compound %}
|
|
||||||
{{ parent() }}
|
|
||||||
{% else %}
|
|
||||||
{% if errors|length > 0 %}
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
{{ parent() }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
{% endspaceless %}
|
|
||||||
{% endblock form_errors %}
|
|
||||||
|
|
||||||
{% block hidden_row %}
|
{% block hidden_row %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
<tr style="display: none">
|
<tr style="display: none">
|
||||||
@ -45,6 +27,13 @@
|
|||||||
{% block form_widget_compound %}
|
{% block form_widget_compound %}
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
<table {{ block('widget_container_attributes') }}>
|
<table {{ block('widget_container_attributes') }}>
|
||||||
|
{% if form.parent is empty and errors|length > 0 %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
{{ form_errors(form) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
{{ block('form_rows') }}
|
{{ block('form_rows') }}
|
||||||
{{ form_rest(form) }}
|
{{ form_rest(form) }}
|
||||||
</table>
|
</table>
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
<div>
|
<div>
|
||||||
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
|
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
|
||||||
<?php if (!$compound): ?>
|
<?php echo $view['form']->errors($form) ?>
|
||||||
<?php echo $view['form']->errors($form) ?>
|
|
||||||
<?php endif ?>
|
|
||||||
<?php echo $view['form']->widget($form) ?>
|
<?php echo $view['form']->widget($form) ?>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
<?php echo $view['form']->errors($form) ?>
|
|
||||||
<?php foreach ($form as $child) : ?>
|
<?php foreach ($form as $child) : ?>
|
||||||
<?php echo $view['form']->row($child) ?>
|
<?php echo $view['form']->row($child) ?>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
<div <?php echo $view['form']->renderBlock('widget_container_attributes') ?>>
|
<div <?php echo $view['form']->renderBlock('widget_container_attributes') ?>>
|
||||||
|
<?php if (!$form->hasParent() && $errors): ?>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<?php echo $view['form']->errors($form) ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endif ?>
|
||||||
<?php echo $view['form']->renderBlock('form_rows') ?>
|
<?php echo $view['form']->renderBlock('form_rows') ?>
|
||||||
<?php echo $view['form']->rest($form) ?>
|
<?php echo $view['form']->rest($form) ?>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,51 +1,21 @@
|
|||||||
<?php if (!$compound): ?>
|
<?php if ($errors): ?>
|
||||||
<?php if ($errors): ?>
|
<ul>
|
||||||
<ul>
|
<?php foreach ($errors as $error): ?>
|
||||||
<?php foreach ($errors as $error): ?>
|
<li><?php
|
||||||
<li><?php
|
if (null === $error->getMessagePluralization()) {
|
||||||
if (null === $error->getMessagePluralization()) {
|
echo $view['translator']->trans(
|
||||||
echo $view['translator']->trans(
|
$error->getMessageTemplate(),
|
||||||
$error->getMessageTemplate(),
|
$error->getMessageParameters(),
|
||||||
$error->getMessageParameters(),
|
'validators'
|
||||||
'validators'
|
);
|
||||||
);
|
} else {
|
||||||
} else {
|
echo $view['translator']->transChoice(
|
||||||
echo $view['translator']->transChoice(
|
$error->getMessageTemplate(),
|
||||||
$error->getMessageTemplate(),
|
$error->getMessagePluralization(),
|
||||||
$error->getMessagePluralization(),
|
$error->getMessageParameters(),
|
||||||
$error->getMessageParameters(),
|
'validators'
|
||||||
'validators'
|
);
|
||||||
);
|
}?></li>
|
||||||
}?></li>
|
<?php endforeach; ?>
|
||||||
<?php endforeach; ?>
|
</ul>
|
||||||
</ul>
|
<?php endif ?>
|
||||||
<?php endif ?>
|
|
||||||
<?php else: ?>
|
|
||||||
<?php if (count($errors) > 0): ?>
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<?php if ($errors): ?>
|
|
||||||
<ul>
|
|
||||||
<?php foreach ($errors as $error): ?>
|
|
||||||
<li><?php
|
|
||||||
if (null === $error->getMessagePluralization()) {
|
|
||||||
echo $view['translator']->trans(
|
|
||||||
$error->getMessageTemplate(),
|
|
||||||
$error->getMessageParameters(),
|
|
||||||
'validators'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
echo $view['translator']->transChoice(
|
|
||||||
$error->getMessageTemplate(),
|
|
||||||
$error->getMessagePluralization(),
|
|
||||||
$error->getMessageParameters(),
|
|
||||||
'validators'
|
|
||||||
);
|
|
||||||
}?></li>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</ul>
|
|
||||||
<?php endif ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endif;
|
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
|
<?php echo $view['form']->label($form, isset($label) ? $label : null) ?>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<?php if (!$compound): ?>
|
<?php echo $view['form']->errors($form) ?>
|
||||||
<?php echo $view['form']->errors($form) ?>
|
|
||||||
<?php endif ?>
|
|
||||||
<?php echo $view['form']->widget($form) ?>
|
<?php echo $view['form']->widget($form) ?>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
<table <?php echo $view['form']->renderBlock('widget_container_attributes') ?>>
|
<table <?php echo $view['form']->renderBlock('widget_container_attributes') ?>>
|
||||||
|
<?php if (!$form->hasParent()): ?>
|
||||||
|
<?php echo $view['form']->errors($form) ?>
|
||||||
|
<?php endif ?>
|
||||||
<?php echo $view['form']->renderBlock('form_rows') ?>
|
<?php echo $view['form']->renderBlock('form_rows') ?>
|
||||||
<?php echo $view['form']->rest($form) ?>
|
<?php echo $view['form']->rest($form) ?>
|
||||||
</table>
|
</table>
|
||||||
|
@ -143,3 +143,4 @@ CHANGELOG
|
|||||||
* FormBuilder now maintains the order when explicitely adding form builders as children
|
* FormBuilder now maintains the order when explicitely adding form builders as children
|
||||||
* ChoiceType now doesn't add the empty value anymore if the choices already contain an empty element
|
* ChoiceType now doesn't add the empty value anymore if the choices already contain an empty element
|
||||||
* DateType, TimeType and DateTimeType now show empty values again if not required
|
* DateType, TimeType and DateTimeType now show empty values again if not required
|
||||||
|
* [BC BREAK] fixed rendering of errors for DateType, BirthdayType and similar ones
|
||||||
|
@ -175,6 +175,11 @@ class FormType extends AbstractType
|
|||||||
return false !== $options['property_path'];
|
return false !== $options['property_path'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Compound forms are not displayed inline
|
||||||
|
$inline = function (Options $options) {
|
||||||
|
return !$options['compound'];
|
||||||
|
};
|
||||||
|
|
||||||
$resolver->setDefaults(array(
|
$resolver->setDefaults(array(
|
||||||
'data' => null,
|
'data' => null,
|
||||||
'data_class' => $dataClass,
|
'data_class' => $dataClass,
|
||||||
@ -195,6 +200,7 @@ class FormType extends AbstractType
|
|||||||
'virtual' => false,
|
'virtual' => false,
|
||||||
'compound' => true,
|
'compound' => true,
|
||||||
'translation_domain' => null,
|
'translation_domain' => null,
|
||||||
|
'inline' => $inline,
|
||||||
));
|
));
|
||||||
|
|
||||||
$resolver->setAllowedTypes(array(
|
$resolver->setAllowedTypes(array(
|
||||||
|
@ -57,11 +57,13 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||||||
$view = $form->createView();
|
$view = $form->createView();
|
||||||
$html = $this->renderRow($view);
|
$html = $this->renderRow($view);
|
||||||
|
|
||||||
|
// The errors of the form are not rendered by intention!
|
||||||
|
// In practice, repeated fields cannot have errors as all errors
|
||||||
|
// on them are mapped to the first child.
|
||||||
|
// (see RepeatedTypeValidatorExtension)
|
||||||
|
|
||||||
$this->assertMatchesXpath($html,
|
$this->assertMatchesXpath($html,
|
||||||
'/ul
|
'/div
|
||||||
[./li[.="[trans]Error![/trans]"]]
|
|
||||||
[count(./li)=1]
|
|
||||||
/following-sibling::div
|
|
||||||
[
|
[
|
||||||
./label[@for="name_first"]
|
./label[@for="name_first"]
|
||||||
/following-sibling::input[@id="name_first"]
|
/following-sibling::input[@id="name_first"]
|
||||||
@ -373,7 +375,8 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
'/div
|
'/div
|
||||||
[
|
[
|
||||||
./div/div[@id="name_child"][./ul/li[.="[trans]Error![/trans]"]]
|
./div/label
|
||||||
|
/following-sibling::ul[./li[.="[trans]Error![/trans]"]]
|
||||||
]
|
]
|
||||||
[count(.//li[.="[trans]Error![/trans]"])=1]
|
[count(.//li[.="[trans]Error![/trans]"])=1]
|
||||||
'
|
'
|
||||||
|
@ -59,12 +59,12 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||||||
/following-sibling::td
|
/following-sibling::td
|
||||||
[./input[@id="name_second"]]
|
[./input[@id="name_second"]]
|
||||||
]
|
]
|
||||||
[count(../tr)=3]
|
|
||||||
/following-sibling::tr[@style="display: none"]
|
/following-sibling::tr[@style="display: none"]
|
||||||
[./td[@colspan="2"]/input
|
[./td[@colspan="2"]/input
|
||||||
[@type="hidden"]
|
[@type="hidden"]
|
||||||
[@id="name__token"]
|
[@id="name__token"]
|
||||||
]
|
]
|
||||||
|
[count(../tr)=3]
|
||||||
'
|
'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -76,12 +76,13 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||||||
$view = $form->createView();
|
$view = $form->createView();
|
||||||
$html = $this->renderRow($view);
|
$html = $this->renderRow($view);
|
||||||
|
|
||||||
|
// The errors of the form are not rendered by intention!
|
||||||
|
// In practice, repeated fields cannot have errors as all errors
|
||||||
|
// on them are mapped to the first child.
|
||||||
|
// (see RepeatedTypeValidatorExtension)
|
||||||
|
|
||||||
$this->assertMatchesXpath($html,
|
$this->assertMatchesXpath($html,
|
||||||
'/tr
|
'/tr
|
||||||
[./td[@colspan="2"]/ul
|
|
||||||
[./li[.="[trans]Error![/trans]"]]
|
|
||||||
]
|
|
||||||
/following-sibling::tr
|
|
||||||
[
|
[
|
||||||
./td
|
./td
|
||||||
[./label[@for="name_first"]]
|
[./label[@for="name_first"]]
|
||||||
@ -95,12 +96,12 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||||||
/following-sibling::td
|
/following-sibling::td
|
||||||
[./input[@id="name_second"]]
|
[./input[@id="name_second"]]
|
||||||
]
|
]
|
||||||
[count(../tr)=4]
|
|
||||||
/following-sibling::tr[@style="display: none"]
|
/following-sibling::tr[@style="display: none"]
|
||||||
[./td[@colspan="2"]/input
|
[./td[@colspan="2"]/input
|
||||||
[@type="hidden"]
|
[@type="hidden"]
|
||||||
[@id="name__token"]
|
[@id="name__token"]
|
||||||
]
|
]
|
||||||
|
[count(../tr)=3]
|
||||||
'
|
'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -235,9 +236,8 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
|
|||||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
'/table
|
'/table
|
||||||
[
|
[
|
||||||
./tr/td/table
|
./tr/td/ul[./li[.="[trans]Error![/trans]"]]
|
||||||
[@id="name_child"]
|
/following-sibling::table[@id="name_child"]
|
||||||
[./tr/td/ul/li[.="[trans]Error![/trans]"]]
|
|
||||||
]
|
]
|
||||||
[count(.//li[.="[trans]Error![/trans]"])=1]
|
[count(.//li[.="[trans]Error![/trans]"])=1]
|
||||||
'
|
'
|
||||||
|
Reference in New Issue
Block a user