Javascript Symfony表单-重新排序/排序集合类型元素

Javascript Symfony表单-重新排序/排序集合类型元素,javascript,jquery,forms,symfony,jquery-ui-sortable,Javascript,Jquery,Forms,Symfony,Jquery Ui Sortable,我正在使用Symfony 2.7创建待办事项列表。表单包含列表名称的简单文本字段和项的集合: class TodoType extends AbstractType { public function getName() { return 'todo_list'; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->

我正在使用Symfony 2.7创建待办事项列表。
表单
包含列表名称的简单文本字段和
项的集合

class TodoType extends AbstractType {
    public function getName() {
        return 'todo_list';
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver) {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\TodoList',
        ));
    }

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
            ->add('name', 'text', array(
                'label' => 'Name',
                ...
            ))
            ->add('create', 'submit', array(
                'label' => 'Save',
                ...
            ));

            $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
                $todoList = $event->getData();
                $form = $event->getForm();

                $form
                    ->add('items', 'collection', array(
                        'type' => 'todo_list_item_type',
                        'allow_add'    => true,
                        'allow_delete' => true,
                        //'by_reference' => false,
                        'data' => ($todoList != null ? $todoList->getItems() : null),
                    ));

            });
        }
    }
}
这个很好用。items数组包含在使用“数组样式”名称的表单中:


...
  • ...
现在我想使用重新排序的项目。这个很好用。用户可以根据自己的喜好对项目进行重新排序。但是,这对项目的存储顺序没有任何影响

我认为问题很明显:可排序插件只会更改
DOM
中项目的位置,而项目名称(包括其数组索引)保持不变。因此,当表单提交时,Item0仍然具有
index=0
,无论它在列表中的新位置如何

是否有任何内置解决方案可以解决此问题?我找到的唯一解决方案是监听可排序插件的
stop
事件(在重新排序完成后触发),并使用一些JavaScript手动查找/替换字段名中的索引号。这当然会起作用,但很容易受到字段名更改的影响。例如,如果Symfony的未来版本将使用
some\u field\u name\u 0
而不是
some\u field\u 0\u name
,则替换代码将不再有效

另一个解决方案是,使用附加字段
sortOrder
扩展
Item
类,并将此信息作为隐藏字段包含在表单中。我仍然需要使用JS手动更新这个索引,但至少我可以更好地控制格式


但是我想知道是否有更简单的方法。对集合类型进行排序没有什么特别的。因此,也许有现成的解决方案?

我认为您的方法是合理的(尽管我将进一步讨论另一种选择)。没有现成的解决方案,收集表单类型依赖于数据“自然”顺序

上一个问题的解决方案是使用“原型”选项。在Twig视图中,您可以显示原型,即集合中任何(新)表单的HTML。
如果您使用
form\u widget
form\u row
,这将自动完成,否则您可以(从文档中)执行此操作:

另一种方法

另一种方法是将
位置
字段添加到
待办事项列表项目
元素中。假设它是一个条令实体,您可以在其上使用可排序的条令扩展:您将在文档中找到所有详细信息,尽管您不需要自己手动启用条令扩展,但您可以使用


如果它是一个简单的数据数组(或者您不想添加扩展名,或者不想将位置保存到数据库),您只需从
setItems
方法中重新排序项目即可。

谢谢!将
\uuuu name\uuuuu
替换为一些自定义内容,在重新设置索引编号时可以轻松识别这些内容,这是一个不错的选择。我已经使用原型向表单中动态添加了新项,在这一步中我可以轻松地更改
\uu name\uu
值。然而,我不明白这对于已经存在并因此加载了表单的项是如何工作的。我对这些值/项没有任何影响。采用您找到的解决方案,重新命名字段,以便将正确的顺序“发送”给Symfony,它将为您提供一个生成新名称的模板。从而使您的解决方案不受您提到的Symfony升级/更改的影响。
<form ...>
    ...
    <ul class="sortable">
       <li>
            <input id="todo_list_items_0_name" class="item-name form-control" type="text" value="Shopping" placeholder="Name" required="required" name="todo_list[items][0][name]">
        </li>
        <li>
            <input id="todo_list_items_1_name" class="item-name form-control" type="text" value="Wash car" placeholder="Name" required="required" name="todo_list[items][1][name]">
        </li>
        ...
    <ul>
<ul class="tags" data-prototype="{{ form_widget(form.tags.vars.prototype)|e('html_attr') }}">
    ...
</ul>
// Get the data-prototype explained earlier
var prototype = $('.tags').data('prototype');

// I assume we use jQuery
var $prototype = $(prototype);

// Get the item name
// by convention, instad of a numeric index it will contain __name__
var itemName = $prototype.attr('name');

// We can replace '__name__' it to whatever you like
var nameFor1 = itemName.replace(/__name__/g, 1);