namespace WF\CORE\CoreBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class WfBaseForm extends AbstractType
{
protected function useFields(FormBuilderInterface $builder, $fields)
{
foreach ($builder->all() as $field) {
if (!in_array($field->getName(), $fields))
$builder->remove($field->getName());
}
}
public function reorder(FormBuilderInterface $builder, $keys = array())
{
$fields = $builder->all();
$ordered_fields = array_merge(array_flip($keys), $fields);
$this->useFields($builder, array());
foreach($ordered_fields as $field)
$builder->add($field);
}
public function getName()
{
return 'base';
}
}
然后你可以在继承的类中使用它。
class AddressType extends WfBaseForm
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// I add as many fields as I need
$builder->add( '…');
}
这个类扩展了上面的类
class ModifyAddressType extends BaseType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->add('title', 'text', array('constraints' => array(new NotBlank())));
$this->reorder($builder, array('title', 'firstname', 'lastname'));
}
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Don't use $builder->add(), or just for those fields which are always
// at the beginning of the form.
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$entry = $event->getData();
$form = $event->getForm();
// Now add all the fields in the order you need them to be, e.g by reading
// the needed order from the data entry.
if ($entry->isFieldAFirst()) {
$form->add(fieldA);
$form->add(fieldB);
} else {
$form->add(fieldB);
$form->add(fieldA);
}
}
}
class ModelA {
private $A;
private $B;
// Getters and setters
}
class ModelB extends ModelA {
private $C;
// Getters and setters
}
/**
* @DI\Service(id = "form.type.modelA")
* @DI\Tag("form.type", attributes={ "alias":"model_a_type" })
*/
class FormAType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('A')
->add('B')
;
}
// getName and so on
}
/**
* @DI\Service(id = "form.type.modelA")
* @DI\Tag("form.type", attributes={ "alias":"model_b_type" })
*/
class FormAType extends AbstractType {
public function getParent() {
return "model_a_type";
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('C')
;
}
// getName and so on
}
8条答案
按热度按时间lpwwtiir1#
您可以使用此捆绑包对字段重新排序:https://github.com/egeloen/IvoryOrderedFormBundle
这允许您执行以下操作:
这将是在核心,但被拒绝,并拉出成一个捆绑。
lztngnrs2#
今天在表单元素排序方面遇到了同样的问题。
最后得到了一个trait,它将覆盖finishView方法,并重新排序FormView的children属性中的项目:
然后在类型中实现getFielddsOrder方法:
bvjxkvbb3#
不需要对字段进行“重新排序”。您需要做的就是为每个字段分别调用
form_label
和/或form_widget
。例如,假设你使用Twig
,你可以这样做:fzwojiic4#
这是我想出的解决办法。
我创建了一个我的类型扩展的类。
然后你可以在继承的类中使用它。
这个类扩展了上面的类
gajydyqb5#
我遇到了同样的问题,但用不同的方式解决了它。这是我的解决方案,作为其他正在寻找这个问题的人的一个想法。
您可以将所有表单字段添加到事件侦听器中,因为这里您有所有对象数据来决定字段顺序。例如,您可以使用来自数据对象的方法来决定字段顺序:
gwbalxhn6#
据我所知,您希望在最终模板中仅使用form_widget(form)。
假设我们有两个继承的模型(ModelA,ModelB)和它们的表单类型(ModelAType,ModelBType)
如果你渲染形式B,你会得到A,B,C顺序,但你想要A,C,B。要完成此操作,请创建表单模板并添加对应用程序的引用。配置文件:
现在,当您呈现formB时,您将看到所需的顺序并保持代码的结构化。这是因为每个小部件只渲染一次,所以如果你在调用父块之前渲染它,你会改变它们的顺序。
lpwwtiir7#
你可以在渲染模板之前在你的控制器中完成:
uasort
也可以工作,但是usort
创建了一个非关联数组,这将在稍后中断表单渲染。qyyhg6bp8#