Skip to content

Commit

Permalink
[Form] Individual rows of CollectionType cannot be styled anymore for…
Browse files Browse the repository at this point in the history
… performance reasons
  • Loading branch information
webmozart committed Jul 14, 2012
1 parent cf41bf8 commit 69e5e58
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 16 deletions.
24 changes: 24 additions & 0 deletions UPGRADE-2.1.md
Expand Up @@ -576,6 +576,30 @@
{% endblock %}
````

* Custom styling of individual rows of a collection form has been removed for
performance reasons. Instead, all rows now have the same block name, where
the word "entry" replaces the previous occurence of the row index.

Before:

```
{% block _author_tags_0_label %}
{# ... #}
{% endblock %}
{% block _author_tags_1_label %}
{# ... #}
{% endblock %}
```

After:

```
{% block _author_tags_entry_label %}
{# ... #}
{% endblock %}
```

#### Other BC Breaks

* The order of the first two arguments of the methods `createNamed` and
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Bridge/Twig/Extension/FormExtension.php
Expand Up @@ -245,7 +245,7 @@ protected function render(FormView $view, $section, array $variables = array())
$this->varStack[$rendering]['variables'] = array_replace_recursive($this->varStack[$rendering]['variables'], $variables);
} else {
$types = $view->getVar('types');
$types[] = $custom;
$types[] = $view->getVar('full_block_name');
$typeIndex = count($types) - 1;
$this->varStack[$rendering] = array(
'variables' => array_replace_recursive($view->getVars(), $variables),
Expand Down
17 changes: 14 additions & 3 deletions src/Symfony/Bridge/Twig/Tests/Extension/custom_widgets.html.twig
@@ -1,5 +1,16 @@
{% block _text_id_widget %}
<div id="container">
{{ form_widget(form) }}
</div>
{% spaceless %}
<div id="container">
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock _text_id_widget %}

{% block _name_entry_label %}
{% spaceless %}
{% if label is empty %}
{% set label = name|humanize %}
{% endif %}
<label>Custom label: {{ label|trans({}, translation_domain) }}</label>
{% endspaceless %}
{% endblock _name_entry_label %}
Expand Up @@ -246,7 +246,7 @@ protected function renderSection(FormView $view, $section, array $variables = ar
$variables = array_replace_recursive($this->varStack[$rendering]['variables'], $variables);
} else {
$types = $view->getVar('types');
$types[] = $custom;
$types[] = $view->getVar('full_block_name');
$typeIndex = count($types) - 1;
$variables = array_replace_recursive($view->getVars(), $variables);
$this->varStack[$rendering]['types'] = $types;
Expand Down
@@ -0,0 +1,2 @@
<?php if (!$label) { $label = $view['form']->humanize($name); } ?>
<label>Custom label: <?php echo $view->escape($view['translator']->trans($label, array(), $translation_domain)) ?></label>
2 changes: 2 additions & 0 deletions src/Symfony/Component/Form/CHANGELOG.md
Expand Up @@ -170,3 +170,5 @@ CHANGELOG
* `getExtensions`
* `setExtensions`
* ChoiceType now caches its created choice lists to improve performance
* [BC BREAK] Rows of a collection field cannot be themed individually anymore. All rows in the collection
field now have the same block names, which contains "entry" where it previously contained the row index.
11 changes: 11 additions & 0 deletions src/Symfony/Component/Form/Extension/Core/Type/CollectionType.php
Expand Up @@ -16,6 +16,7 @@
use Symfony\Component\Form\FormViewInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CollectionType extends AbstractType
Expand Down Expand Up @@ -73,6 +74,12 @@ public function finishView(FormViewInterface $view, FormInterface $form, array $
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$optionsFilter = function (Options $options, $value) {
$value['block_name'] = 'entry';

return $value;
};

$resolver->setDefaults(array(
'allow_add' => false,
'allow_delete' => false,
Expand All @@ -81,6 +88,10 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
'type' => 'text',
'options' => array(),
));

$resolver->setFilters(array(
'options' => $optionsFilter,
));
}

/**
Expand Down
32 changes: 21 additions & 11 deletions src/Symfony/Component/Form/Extension/Core/Type/FormType.php
Expand Up @@ -59,6 +59,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
public function buildView(FormViewInterface $view, FormInterface $form, array $options)
{
$name = $form->getName();
$blockName = $options['block_name'] ?: $form->getName();
$readOnly = $options['read_only'];
$translationDomain = $options['translation_domain'];

Expand All @@ -67,23 +68,30 @@ public function buildView(FormViewInterface $view, FormInterface $form, array $o
throw new FormException('Form node with empty name can be used only as root form node.');
}

if ('' !== ($parentFullName = $view->getParent()->getVar('full_name'))) {
$id = sprintf('%s_%s', $view->getParent()->getVar('id'), $name);
$parentView = $view->getParent();

if ('' !== ($parentFullName = $parentView->getVar('full_name'))) {
$id = sprintf('%s_%s', $parentView->getVar('id'), $name);
$fullName = sprintf('%s[%s]', $parentFullName, $name);
$fullBlockName = sprintf('%s_%s', $parentView->getVar('full_block_name'), $blockName);
} else {
$id = $name;
$fullName = $name;
$fullBlockName = '_' . $blockName;
}

// Complex fields are read-only if themselves or their parent is.
$readOnly = $readOnly || $view->getParent()->getVar('read_only');
// Complex fields are read-only if they themselves or their parents are.
if (!$readOnly) {
$readOnly = $parentView->getVar('read_only');
}

if (!$translationDomain) {
$translationDomain = $view->getParent()->getVar('translation_domain');
$translationDomain = $parentView->getVar('translation_domain');
}
} else {
$id = $name;
$fullName = $name;
$fullBlockName = '_' . $blockName;

// Strip leading underscores and digits. These are allowed in
// form names, but not in HTML4 ID attributes.
Expand All @@ -105,6 +113,7 @@ public function buildView(FormViewInterface $view, FormInterface $form, array $o
'id' => $id,
'name' => $name,
'full_name' => $fullName,
'full_block_name' => $fullBlockName,
'read_only' => $readOnly,
'errors' => $form->getErrors(),
'valid' => $form->isBound() ? $form->isValid() : true,
Expand Down Expand Up @@ -177,7 +186,14 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
return false !== $options['property_path'];
};

// If data is given, the form is locked to that data
// (independent of its value)
$resolver->setOptional(array(
'data',
));

$resolver->setDefaults(array(
'block_name' => null,
'data_class' => $dataClass,
'empty_data' => $emptyData,
'trim' => true,
Expand All @@ -198,12 +214,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
'translation_domain' => null,
));

// If data is given, the form is locked to that data
// (independent of its value)
$resolver->setOptional(array(
'data',
));

$resolver->setAllowedTypes(array(
'attr' => 'array',
'label_attr' => 'array',
Expand Down
21 changes: 21 additions & 0 deletions src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php
Expand Up @@ -557,6 +557,27 @@ public function testThemeInheritance($parentTheme, $childTheme)
]
/following-sibling::input[@type="hidden"]
]
'
);
}

/**
* The block "_name_child_label" should be overridden in the theme of the
* implemented driver.
*/
public function testCollectionRowWithCustomBlock()
{
$collection = array('one', 'two', 'three');
$form = $this->factory->createNamedBuilder('name', 'collection', $collection)
->getForm();

$this->assertWidgetMatchesXpath($form->createView(), array(),
'/div
[
./div[./label[.="Custom label: [trans]0[/trans]"]]
/following-sibling::div[./label[.="Custom label: [trans]1[/trans]"]]
/following-sibling::div[./label[.="Custom label: [trans]2[/trans]"]]
]
'
);
}
Expand Down
21 changes: 21 additions & 0 deletions src/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php
Expand Up @@ -338,6 +338,27 @@ public function testRepeatedWithCustomOptions()
]
]
[count(.//input)=3]
'
);
}

/**
* The block "_name_child_label" should be overridden in the theme of the
* implemented driver.
*/
public function testCollectionRowWithCustomBlock()
{
$collection = array('one', 'two', 'three');
$form = $this->factory->createNamedBuilder('name', 'collection', $collection)
->getForm();

$this->assertWidgetMatchesXpath($form->createView(), array(),
'/table
[
./tr[./td/label[.="Custom label: [trans]0[/trans]"]]
/following-sibling::tr[./td/label[.="Custom label: [trans]1[/trans]"]]
/following-sibling::tr[./td/label[.="Custom label: [trans]2[/trans]"]]
]
'
);
}
Expand Down

0 comments on commit 69e5e58

Please sign in to comment.