gpt4 book ai didi

Symfony2 : Radio buttons in a collection

转载 作者:行者123 更新时间:2023-12-03 21:54:50 24 4
gpt4 key购买 nike

在我的应用程序中,我使用 collection 创建了一个表单。字段类型:

$builder->add('tags', 'collection', array(
'type' => new TagType(),
'label' => false,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
));

使用一些 JQuery,这段代码可以正常工作,但现在我想选择这个动态标签之一,使其成为“主标签”。

在我的标签实体中,我添加了一个 bool 属性,它定义标签是否是主要的:
/**
* @ORM\Column(name="main", type="boolean")
*/
private $main;

但在我看来,每一行现在都包含一个复选框。所以我可以选择多个主标签。请问如何在单选按钮中转换此复选框?

最佳答案

你没有从正确的角度解决问题。如果应该有一个主标签,那么这个属性不应该被添加到 中。标签 实体本身,但在包含它的实体中!

我说的是与具有 的表单相关的 data_class 实体。标签 属性。这是应该具有 的实体主标签 属性(property)。

如果定义正确,这个新的主标签 属性不会是 bool 值,因为它将包含 标签 实例,因此不会与复选框条目相关联。

所以,在我看来,你应该有一个 主标签 包含您的实例和 的属性标签 包含所有其他标签的属性。

这样做的问题是您的收藏字段将不再包含主标签。因此,您还应该创建一个特殊的 getter 获取所有标签 这会将您的主要标签与所有其他标签合并,并将您的集合定义更改为:

$builder->add('allTags', 'collection', array(
'type' => new TagType(),
'label' => false,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
));

现在,您可能会问,我们如何添加单选框?为此,您必须生成一个新字段:
$builder->add('mainTag', 'radio', array(
'type' => 'choice',
'multiple' => false,
'expanded' => true,
'property_path' => 'mainTag.id', // Necessary, for 'choice' does not support data_classes
));

这些是基础知识,但它只会从这里变得更加复杂。这里真正的问题是表单的显示方式。在同一个字段中,您混合了集合的通常显示和该集合的父表单的选择字段的显示。这将迫使您使用 form theming .

为了给可重用性留出一些空间,您需要创建一个自定义字段。相关的数据类:
class TagSelection
{
private mainTag;

private $tags;

public function getAllTags()
{
return array_merge(array($this->getMainTag()), $this->getTags());
}

public function setAllTags($tags)
{
// If the main tag is not null, search and remove it before calling setTags($tags)
}

// Getters, setters
}

表格类型:
class TagSelectionType extends AbstractType
{
protected buildForm( ... )
{
$builder->add('allTags', 'collection', array(
'type' => new TagType(),
'label' => false,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
));

// Since we cannot know which tags are available before binding or setting data, a listener must be used
$formFactory = $builder->getFormFactory();
$listener = function(FormEvent $event) use ($formFactory) {

$data = $event->getForm()->getData();

// Get all tags id currently in the data
$choices = ...;
// Careful, in PRE_BIND this is an array of scalars while in PRE_SET_DATA it is an array of Tag instances

$field = $this->factory->createNamed('mainTag', 'radio', null, array(
'type' => 'choice',
'multiple' => false,
'expanded' => true,
'choices' => $choices,
'property_path' => 'mainTag.id',
));
$event->getForm()->add($field);
}

$builder->addEventListener(FormEvent::PRE_SET_DATA, $listener);
$builder->addEventListener(FormEvent::PRE_BIND, $listener);
}

public function getName()
{
return 'tag_selection';
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TagSelection', // Adapt depending on class name
// 'prototype' => true,
));
}
}

最后,在表单主题模板中:
{% block tag_selection_widget %}
{% spaceless %}
{# {% set attr = attr|default({})|merge({'data-prototype': form_widget(prototype)}) %} #}
<ul {{ block('widget_attributes') }}>
{% for child in form.allTags %}
<li>{{ form_widget(form.mainTag[child.name]) }} {{ form_widget(child) }}</li>
{% endfor %}
</ul>
{% endspaceless %}
{% endblock tag_selection_widget %}

最后,我们需要将它包含在您的父实体中,即最初包含 的实体。标签 :
class entity
{
// Doctrine definition and whatnot
private $tags;

// Doctrine definition and whatnot
private $mainTag;

...
public setAllTags($tagSelection)
{
$this->setMainTag($tagSelection->getMainTag());
$this->setTags($tagSelection->getTags());
}

public getAllTags()
{
$ret = new TagSelection();
$ret->setMainTag($this->getMainTag());
$ret->setTags($this->getTags());

return $ret;
}

...
}

并以您的原始形式:
$builder->add('allTags', new TagSelection(), array(
'label' => false,
));

我承认我提出的解决方案很冗长,但在我看来它是最有效的。你想要做的事情在 Symfony 中是不容易做到的。

您还可以注意到评论中有一个奇怪的“原型(prototype)”选项。在您的情况下,我只是想强调“集合”的一个非常有用的属性:原型(prototype)选项包含您的集合的一个空白项目,并带有要替换的占位符。这允许使用 javascript 在集合字段中快速添加新项目,更多信息 here .

关于Symfony2 : Radio buttons in a collection,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21001536/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com