diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig
index d69e42ab40f4..c3e207bdc821 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig
@@ -164,6 +164,9 @@
font-weight: bold;
vertical-align: middle;
}
+ .has-error {
+ color: #B0413E;
+ }
.errors h3 {
color: #B0413E;
}
@@ -423,11 +426,12 @@
{% endblock %}
-{% macro form_tree_entry(name, data, expanded) %}
+{% macro form_tree_entry(name, data, is_root) %}
{% import _self as tree %}
+ {% set has_error = data.errors is defined and data.errors|length > 0 %}
- {% if data.errors is defined and data.errors|length > 0 %}
+ {% if has_error %}
{{ data.errors|length }}
{% endif %}
@@ -437,11 +441,13 @@
{% endif %}
- {{ name|default('(no name)') }} {% if data.type_class is defined %}[
{{ data.type_class|split('\\')|last }}]{% endif %}
+
+ {{ name|default('(no name)') }} {% if data.type_class is defined %}[{{ data.type_class|split('\\')|last }}]{% endif %}
+
{% if data.children is not empty %}
-
+
{% for childName, childData in data.children %}
{{ tree.form_tree_entry(childName, childData, false) }}
{% endfor %}
diff --git a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php
index a408dde2306c..ec817c4e2c0a 100644
--- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php
+++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php
@@ -155,6 +155,12 @@ public function collectSubmittedData(FormInterface $form)
foreach ($form as $child) {
$this->collectSubmittedData($child);
+
+ // Expand current form if there are children with errors
+ if (empty($this->dataByForm[$hash]['has_children_error'])) {
+ $childData = $this->dataByForm[spl_object_hash($child)];
+ $this->dataByForm[$hash]['has_children_error'] = !empty($childData['has_children_error']) || !empty($childData['errors']);
+ }
}
}
diff --git a/src/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php b/src/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php
index f6fa2493d55c..0fddf14dc57b 100644
--- a/src/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php
+++ b/src/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php
@@ -123,6 +123,7 @@ public function testBuildPreliminaryFormTree()
'config' => 'foo',
'default_data' => 'foo',
'submitted_data' => 'foo',
+ 'has_children_error' => false,
'children' => array(
'child' => $childFormData,
),
@@ -323,6 +324,7 @@ public function testBuildFinalFormTree()
'config' => 'foo',
'default_data' => 'foo',
'submitted_data' => 'foo',
+ 'has_children_error' => false,
'children' => array(
'child' => $childFormData,
),
@@ -528,6 +530,62 @@ public function testCollectSubmittedDataCountsErrors()
$this->assertSame(4, $data['nb_errors']);
}
+ public function testCollectSubmittedDataExpandedFormsErrors()
+ {
+ $child1Form = $this->createForm('child1');
+ $child11Form = $this->createForm('child11');
+ $child2Form = $this->createForm('child2');
+ $child21Form = $this->createForm('child21');
+
+ $child1Form->add($child11Form);
+ $child2Form->add($child21Form);
+ $this->form->add($child1Form);
+ $this->form->add($child2Form);
+
+ $this->dataExtractor
+ ->method('extractConfiguration')
+ ->will($this->returnValue(array()));
+ $this->dataExtractor
+ ->method('extractDefaultData')
+ ->will($this->returnValue(array()));
+ $this->dataExtractor->expects($this->at(10))
+ ->method('extractSubmittedData')
+ ->with($this->form)
+ ->will($this->returnValue(array('errors' => array())));
+ $this->dataExtractor->expects($this->at(11))
+ ->method('extractSubmittedData')
+ ->with($child1Form)
+ ->will($this->returnValue(array('errors' => array())));
+ $this->dataExtractor->expects($this->at(12))
+ ->method('extractSubmittedData')
+ ->with($child11Form)
+ ->will($this->returnValue(array('errors' => array('foo'))));
+ $this->dataExtractor->expects($this->at(13))
+ ->method('extractSubmittedData')
+ ->with($child2Form)
+ ->will($this->returnValue(array('errors' => array())));
+ $this->dataExtractor->expects($this->at(14))
+ ->method('extractSubmittedData')
+ ->with($child21Form)
+ ->will($this->returnValue(array('errors' => array())));
+
+ $this->dataCollector->collectSubmittedData($this->form);
+ $this->dataCollector->buildPreliminaryFormTree($this->form);
+
+ $data = $this->dataCollector->getData();
+ $formData = $data['forms']['name'];
+ $child1Data = $formData['children']['child1'];
+ $child11Data = $child1Data['children']['child11'];
+ $child2Data = $formData['children']['child2'];
+ $child21Data = $child2Data['children']['child21'];
+
+ $this->assertTrue($formData['has_children_error']);
+ $this->assertTrue($child1Data['has_children_error']);
+ $this->assertFalse(isset($child11Data['has_children_error']), 'The leaf data does not contains "has_children_error" property.');
+ $this->assertFalse($child2Data['has_children_error']);
+ $this->assertFalse(isset($child21Data['has_children_error']), 'The leaf data does not contains "has_children_error" property.');
+ }
+
private function createForm($name)
{
$builder = new FormBuilder($name, null, $this->dispatcher, $this->factory);