8000 feature #48343 [Form] [ChoiceType] Add a `placeholder_attr` option (e… · symfony/symfony@3067b9b · GitHub
[go: up one dir, main page]

Skip to content

Commit 3067b9b

Browse files
committed
feature #48343 [Form] [ChoiceType] Add a placeholder_attr option (elementaire)
This PR was merged into the 6.3 branch. Discussion ---------- [Form] [ChoiceType] Add a `placeholder_attr` option | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | #38958 | Similar Pull Request | #47570 | License | MIT | Doc PR | symfony/symfony-docs#17469 Allow to custom the attributes of the placeholder (`data-*`, `title`, `disabled`, etc.). Commits ------- 2d4396a [Form][ChoiceType] Add placeholder_attr field option
2 parents 4610857 + 2d4396a commit 3067b9b

File tree

7 files changed

+66
-40
lines changed
  • < 8000 div style="width:100%;display:flex">
    src/Symfony

7 files changed

+66
-40
lines changed

src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
{%- endif -%}
6262
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
6363
{%- if placeholder is not none -%}
64-
<option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ placeholder != '' ? (translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain)) }}</option>
64+
<option value=""{% if placeholder_attr|default({}) %}{% with { attr: placeholder_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}{% if required and value is empty %} selected="selected"{% endif %}>{{ placeholder != '' ? (translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain)) }}</option>
6565
{%- endif -%}
6666
{%- if preferred_choices|length > 0 -%}
6767
{% set options = preferred_choices %}

src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@
156156
{%- endif -%}
157157
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple" data-customforms="disabled"{% endif %}>
158158
{% if placeholder is not none -%}
159-
<option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain) }}</option>
159+
<option value=""{% if placeholder_attr|default({}) %}{% with { attr: placeholder_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}{% if required and value is empty %} selected="selected"{% endif %}>{{ translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain) }}</option>
160160
{%- endif %}
161161
{%- if preferred_choices|length > 0 -%}
162162
{% set options = preferred_choices %}

src/Symfony/Component/Form/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
6.3
5+
---
6+
7+
* Add a `placeholder_attr` option to `ChoiceType`
8+
49
6.2
510
---
611

src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
8484
// Check if the choices already contain the empty value
8585
// Only add the placeholder option if this is not the case
8686
if (null !== $options['placeholder'] && 0 === \count($choiceList->getChoicesForValues(['']))) {
87-
$placeholderView = new ChoiceView(null, '', $options['placeholder']);
87+
$placeholderView = new ChoiceView(null, '', $options['placeholder'], $options['placeholder_attr']);
8888

8989
// "placeholder" is a reserved name
9090
$this->addSubForm($builder, 'placeholder', $placeholderView, $options);
@@ -237,6 +237,7 @@ public function buildView(FormView $view, FormInterface $form, array $options)
237237
'choices' => $choiceListView->choices,
238238
'separator' => '-------------------',
239239
'placeholder' => null,
240+
'placeholder_attr' => [],
240241
'choice_translation_domain' => $choiceTranslationDomain,
241242
'choice_translation_parameters' => $options['choice_translation_parameters'],
242243
]);
@@ -257,6 +258,7 @@ public function buildView(FormView $view, FormInterface $form, array $options)
257258
// Only add the empty value option if this is not the case
258259
if (null !== $options['placeholder'] && !$view->vars['placeholder_in_choices']) {
259260
$view->vars['placeholder'] = $options['placeholder'];
261+
$view->vars['placeholder_attr'] = $options['placeholder_attr'];
260262
}
261263

262264
if ($options['multiple'] && !$options['expanded']) {
@@ -344,6 +346,7 @@ public function configureOptions(OptionsResolver $resolver)
344346
'group_by' => null,
345347
'empty_data' => $emptyData,
346348
'placeholder' => $placeholderDefault,
349+
'placeholder_attr' => [],
347350
'error_bubbling' => false,
348351
'compound' => $compound,
349352
// The view data is always a string or an array of strings,
@@ -367,6 +370,7 @@ public function configureOptions(OptionsResolver $resolver)
367370
$resolver->setAllowedTypes('choice_value', ['null', 'callable', 'string', PropertyPath::class, ChoiceValue::class]);
368371
$resolver->setAllowedTypes('choice_attr', ['null', 'array', 'callable', 'string', PropertyPath::class, ChoiceAttr::class]);
369372
$resolver->setAllowedTypes('choice_translation_parameters', ['null', 'array', 'callable', ChoiceTranslationParameters::class]);
373+
$resolver->setAllowedTypes('placeholder_attr', ['array']);
370374
$resolver->setAllowedTypes('preferred_choices', ['array', \Traversable::class, 'callable', 'string', PropertyPath::class, PreferredChoice::class]);
371375
$resolver->setAllowedTypes('group_by', ['null', 'callable', 'string', PropertyPath::class, GroupBy::class]);
372376
}

src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php

Lines changed: 51 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@ public function testChoiceLoaderOptionExpectsChoiceLoaderInterface()
100100
]);
101101
}
102102

103+
public function testPlaceholderAttrOptionExpectsArray()
104+
{
105+
$this->expectException(InvalidOptionsException::class);
106+
$this->factory->create(static::TESTED_TYPE, null, [
107+
'placeholder_attr' => new \stdClass(),
108+
]);
109+
}
110+
103111
public function testChoiceListAndChoicesCanBeEmpty()
104112
{
105113
$this->assertInstanceOf(FormInterface::class, $this->factory->create(static::TESTED_TYPE, null, []));
@@ -189,15 +197,19 @@ public function testExpandedChoiceListWithBooleanAndNullValuesAndFalseAsPreSetDa
189197

190198
public function testPlaceholderPresentOnNonRequiredExpandedSingleChoice()
191199
{
200+
$placeholderAttr = ['attr' => 'value'];
201+
192202
$form = $this->factory->create(static::TESTED_TYPE, null, [
193203
'multiple' => false,
194204
'expanded' => true,
195205
'required' => false,
196206
'choices' => $this->choices,
207+
'placeholder_attr' => $placeholderAttr,
197208
]);
198209

199210
$this->assertArrayHasKey('placeholder', $form);
200211
$this->assertCount(\count($this->choices) + 1, $form, 'Each choice should become a new field');
212+
$this->assertSame($placeholderAttr, $form->createView()->children['placeholder']->vars['attr']);
201213
}
202214

203215
public function testPlaceholderNotPresentIfRequired()
@@ -1667,80 +1679,84 @@ public function testPlaceholderIsEmptyStringByDefaultIfNotRequired()
16671679
/**
16681680
* @dataProvider getOptionsWithPlaceholder
16691681
*/
1670-
public function testPassPlaceholderToView($multiple, $expanded, $required, $placeholder, $viewValue)
1682+
public function testPassPlaceholderToView($multiple, $expanded, $required, $placeholder, $placeholderViewValue, $placeholderAttr, $placeholderAttrViewValue)
16711683
{
16721684
$view = $this->factory->create(static::TESTED_TYPE, null, [
16731685
'multiple' => $multiple,
16741686
'expanded' => $expanded,
16751687
'required' => $required,
16761688
'placeholder' => $placeholder,
1689+
'placeholder_attr' => $placeholderAttr,
16771690
'choices' => $this->choices,
16781691
])
16791692
->createView();
16801693

1681-
$this->assertSame($viewValue, $view->vars['placeholder']);
1694+
$this->assertSame($placeholderViewValue, $view->vars['placeholder']);
1695+
$this->assertSame($placeholderAttrViewValue, $view->vars['placeholder_attr']);
16821696
$this->assertFalse($view->vars['placeholder_in_choices']);
16831697
}
16841698

16851699
/**
16861700
* @dataProvider getOptionsWithPlaceholder
16871701
*/
1688-
public function testDontPassPlaceholderIfContainedInChoices($multiple, $expanded, $required, $placeholder, $viewValue)
1702+
public function testDontPassPlaceholderIfContainedInChoices($multiple, $expanded, $required, $placeholder, $placeholderViewValue, $placeholderAttr, $placeholderAttrViewValue)
16891703
{
16901704
$view = $this->factory->create(static::TESTED_TYPE, null, [
16911705
'multiple' => $multiple,
16921706< 1241 /td>
'expanded' => $expanded,
16931707
'required' => $required,
16941708
'placeholder' => $placeholder,
1709+
'placeholder_attr' => $placeholderAttr,
16951710
'choices' => ['Empty' => '', 'A' => 'a'],
16961711
])
16971712
->createView();
16981713

16991714
$this->assertNull($view->vars['placeholder']);
1715+
$this->assertSame([], $view->vars['placeholder_attr']);
17001716
$this->assertTrue($view->vars['placeholder_in_choices']);
17011717
}
17021718

17031719
public static function getOptionsWithPlaceholder()
17041720
{
17051721
return [
17061722
// single non-expanded
1707-
[false, false, false, 'foobar', 'foobar'],
1708-
[false, false, false, '', ''],
1709-
[false, false, false, null, null],
1710-
[false, false, false, false, null],
1711-
[false, false, true, 'foobar', 'foobar'],
1712-
[false, false, true, '', ''],
1713-
[false, false, true, null, null],
1714-
[false, false, true, false, null],
1723+
[false, false, false, 'foobar', 'foobar', ['attr' => 'value'], ['attr' => 'value']],
1724+
[false, false, false, '', '', ['attr' => 'value'], ['attr' => 'value']],
1725+
[false, false, false, null, null, ['attr' => 'value'], []],
1726+
[false, false, false, false, null, ['attr' => 'value'], []],
1727+
[false, false, true, 'foobar', 'foobar', ['attr' => 'value'], ['attr' => 'value']],
1728+
[false, false, true, '', '', ['attr' => 'value'], ['attr' => 'value']],
1729+
[false, false, true, null, null, ['attr' => 'value'], []],
1730+
[false, false, true, false, null, ['attr' => 'value'], []],
17151731
// single expanded
1716-
[false, true, false, 'foobar', 'foobar'],
1732+
[false, true, false, 'foobar', 'foobar', ['attr' => 'value'], ['attr' => 'value']],
17171733
// radios should never have an empty label
1718-
[false, true, false, '', 'None'],
1719-
[false, true, false, null, null],
1720-
[false, true, false, false, null],
1734+
[false, true, false, '', 'None', ['attr' => 'value'], ['attr' => 'value']],
1735+
[false, true, false, null, null, ['attr' => 'value'], []],
1736+
[false, true, false, false, null, ['attr' => 'value'], []],
17211737
// required radios should never have a placeholder
1722-
[false, true, true, 'foobar', null],
1723-
[false, true, true, '', null],
1724-
[false, true, true, null, null],
1725-
[false, true, true, false, null],
1738+
[false, true, true, 'foobar', null, ['attr' => 'value'], []],
1739+
[false, true, true, '', null, ['attr' => 'value'], []],
1740+
[false, true, true, null, null, ['attr' => 'value'], []],
1741+
[false, true, true, false, null, ['attr' => 'value'], []],
17261742
// multiple non-expanded
1727-
[true, false, false, 'foobar', null],
1728-
[true, false, false, '', null],
1729-
[true, false, false, null, null],
1730-
[true, false, false, false, null],
1731-
[true, false, true, 'foobar', null],
1732-
[true, false, true, '', null],
1733-
[true, false, true, null, null],
1734-
[true, false, true, false, null],
1743+
[true, false, false, 'foobar', null, ['attr' => 'value'], []],
1744+
[true, false, false, '', null, ['attr' => 'value'], []],
1745+
[true, false, false, null, null, ['attr' => 'value'], []],
1746+
[true, false, false, false, null, ['attr' => 'value'], []],
1747+
[true, false, true, 'foobar', null, ['attr' => 'value'], []],
1748+
[true, false, true, '', null, ['attr' => 'value'], []],
1749+
[true, false, true, null, null, ['attr' => < 10000 span class="x">'value'], []],
1750+
[true, false, true, false, null, ['attr' => 'value'], []],
17351751
// multiple expanded
1736-
[true, true, false, 'foobar', null],
1737-
[true, true, false, '', null],
1738-
[true, true, false, null, null],
1739-
[true, true, false, false, null],
1740-
[true, true, true, 'foobar', null],
1741-
[true, true, true, '', null],
1742-
[true, true, true, null, null],
1743-
[true, true, true, false, null],
1752+
[true, true, false, 'foobar', null, ['attr' => 'value'], []],
1753+
[true, true, false, '', null, ['attr' => 'value'], []],
1754+
[true, true, false, null, null, ['attr' => 'value'], []],
1755+
[true, true, false, false, null, ['attr' => 'value'], []],
1756+
[true, true, true, 'foobar', null, ['attr' => 'value'], []],
1757+
[true, true, true, '', null, ['attr' => 'value'], []],
1758+
[true, true, true, null, null, ['attr' => 'value'], []],
1759+
[true, true, true, false, null, ['attr' => 'value'], []],
17441760
];
17451761
}
17461762

src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"group_by",
1717
"multiple",
1818
"placeholder",
19+
"placeholder_attr",
1920
"preferred_choices"
2021
],
2122
"overridden": {

src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ Symfony\Component\Form\Extension\Core\Type\ChoiceType (Block prefix: "choice")
1818
group_by data
1919
multiple disabled
2020
placeholder form_attr
21-
preferred_choices getter
22-
help
21+
placeholder_attr getter
22+
preferred_choices help
2323
help_attr
2424
help_html
2525
help_translation_parameters

0 commit comments

Comments
 (0)
0