diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_attributes.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_attributes.html.php
new file mode 100644
index 0000000000000..8d2d6d7fd63c3
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_attributes.html.php
@@ -0,0 +1,9 @@
+id="escape($id) ?>" name="escape($full_name) ?>"
+disabled="disabled"
+ $v): ?>
+
+escape($k), $view->escape($k)) ?>
+
+escape($k), $view->escape($v)) ?>
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_widget_options.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_widget_options.html.php
index a0363cc5a47b8..f1c6ad3b56f21 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_widget_options.html.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_widget_options.html.php
@@ -8,6 +8,6 @@
block($form, 'choice_widget_options', array('choices' => $choice)) ?>
-
+
diff --git a/src/Symfony/Component/Form/Tests/AbstractBootstrap3LayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractBootstrap3LayoutTest.php
index ee260bd0c84a7..c3e1b3bd8afe0 100644
--- a/src/Symfony/Component/Form/Tests/AbstractBootstrap3LayoutTest.php
+++ b/src/Symfony/Component/Form/Tests/AbstractBootstrap3LayoutTest.php
@@ -232,6 +232,68 @@ public function testSingleChoice()
);
}
+ public function testSingleChoiceAttributesWithMainAttributes()
+ {
+ $form = $this->factory->createNamed('name', 'choice', '&a', array(
+ 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
+ 'choices_as_values' => true,
+ 'multiple' => false,
+ 'expanded' => false,
+ 'attr' => array('class' => 'bar&baz'),
+ ));
+
+ $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'bar&baz')),
+'/select
+ [@name="name"]
+ [@class="bar&baz form-control"]
+ [not(@required)]
+ [
+ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
+ /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
+ ]
+ [count(./option)=2]
+'
+ );
+ }
+
+ public function testSingleExpandedChoiceAttributesWithMainAttributes()
+ {
+ $form = $this->factory->createNamed('name', 'choice', '&a', array(
+ 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
+ 'choices_as_values' => true,
+ 'multiple' => false,
+ 'expanded' => true,
+ 'attr' => array('class' => 'bar&baz'),
+ ));
+
+ $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'bar&baz')),
+'/div
+ [@class="bar&baz"]
+ [
+ ./div
+ [@class="radio"]
+ [
+ ./label
+ [.=" [trans]Choice&A[/trans]"]
+ [
+ ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
+ ]
+ ]
+ /following-sibling::div
+ [@class="radio"]
+ [
+ ./label
+ [.=" [trans]Choice&B[/trans]"]
+ [
+ ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
+ ]
+ ]
+ /following-sibling::input[@type="hidden"][@id="name__token"]
+ ]
+'
+ );
+ }
+
public function testSelectWithSizeBiggerThanOneCanBeRequired()
{
$form = $this->factory->createNamed('name', 'choice', null, array(
diff --git a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php
index c31513e2094fe..cad57cabb5fc8 100644
--- a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php
+++ b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php
@@ -596,6 +596,55 @@ public function testSingleChoiceAttributes()
);
}
+ public function testSingleChoiceAttributesWithMainAttributes()
+ {
+ $form = $this->factory->createNamed('name', 'choice', '&a', array(
+ 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
+ 'choices_as_values' => true,
+ 'multiple' => false,
+ 'expanded' => false,
+ 'attr' => array('class' => 'bar&baz'),
+ ));
+
+ $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'bar&baz')),
+'/select
+ [@name="name"]
+ [@class="bar&baz"]
+ [not(@required)]
+ [
+ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
+ /following-sibling::option[@value="&b"][not(@class)][not(@selected)][.="[trans]Choice&B[/trans]"]
+ ]
+ [count(./option)=2]
+'
+ );
+ }
+
+ public function testSingleExpandedChoiceAttributesWithMainAttributes()
+ {
+ $form = $this->factory->createNamed('name', 'choice', '&a', array(
+ 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
+ 'choices_as_values' => true,
+ 'multiple' => false,
+ 'expanded' => true,
+ 'attr' => array('class' => 'bar&baz'),
+ ));
+
+ $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'bar&baz')),
+'/div
+ [@class="bar&baz"]
+ [
+ ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
+ /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
+ /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
+ /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
+ /following-sibling::input[@type="hidden"][@id="name__token"]
+ ]
+ [count(./input)=3]
+'
+ );
+ }
+
public function testSingleChoiceWithPreferred()
{
$form = $this->factory->createNamed('name', 'choice', '&a', array(