对称/symfony-collection

一个jQuery插件,用于管理从Symfony集合中添加、删除和移动元素

安装次数: 1 823 957

依赖者: 5

建议者: 0

安全性: 0

星标: 444

关注者: 22

分支: 88

开放性问题: 54

语言:JavaScript

2.1.33 2020-01-13 12:54 UTC

README

一个jQuery插件,用于管理从Symfony集合中添加、删除和移动元素

sample

使用Symfony提供的data-prototype管理集合并不困难。但是,在使用了几次集合后,我觉得创建一个jQuery插件来做这项工作很有用。

特别是当你需要你的元素可以上下移动或添加到特定位置时:由于表单将通过字段名称进行操作,我们应该交换字段内容或字段名称,而不是移动字段本身来完成这项工作。这在JavaScript中并不友好,因此这个插件也旨在处理这种情况。

在线演示

此插件的演示可在以下地址实时查看:http://symfony-collection.fuz.org

演示源代码在此:https://github.com/ninsuo/symfony-collection-demo

安装

此插件包含2个文件

  • jQuery插件本身,应该位于您的资源文件中

  • 一个用于简化使用的twig表单主题,应该位于您的视图文件中

使用Composer安装

要自动化插件下载和安装,编辑composer.json并添加

    "require": {
        ...
        "ninsuo/symfony-collection": "dev-master"
    },
    "scripts": {
        "post-install-cmd": [
            ...
            "Fuz\\Symfony\\Collection\\ScriptHandler::postInstall"
        ],
        "post-update-cmd": [
            ...
            "Fuz\\Symfony\\Collection\\ScriptHandler::postUpdate"
        ]
    }

文件将自动安装到以下位置

  • symfony-collection表单主题将安装在app/Resources/views

  • symfony-collection jQuery插件将安装在web/js

提示

  • dev-master替换为当前稳定版本。

  • 如果希望利用资源文件优化,请在Symfony的installAssets之前放置脚本处理器。

  • app/Resources/views/jquery.collection.html.twigweb/js/jquery.collection.js添加到您的.gitignore

如果您更喜欢手动安装插件,可以使用

composer require ninsuo/symfony-collection

您需要将以下文件移动到您的资源文件中

  • vendor/ninsuo/symfony-collection/jquery.collection.js(例如,在web/js中)

  • vendor/ninsuo/symfony-collection/jquery.collection.html.twig(例如,在app/Resources/views中)

使用npm安装

npm install ninsuo/symfony-collection

您需要将以下文件移动到您的资源文件中

  • node_modules/symfony-collection/jquery.collection.js(例如,在web/js中)。
  • node_modules/symfony-collection/jquery.collection.html.twig(例如,在app/Resources/views中)。

使用Bower安装

bower install ninsuo/symfony-collection

您需要将以下文件移动到您的资源文件中

  • bower_components/symfony-collection/jquery.collection.js(例如,在web/js中)。
  • bower_components/symfony-collection/jquery.collection.html.twig(例如,在app/Resources/views中)。

基本用法

一个简单的集合

您的集合类型应该包含prototypeallow_addallow_remove选项(当然取决于您需要的按钮)。以及一个用作选择器的类,用于运行集合插件。

->add('myCollection', 'collection',
   array (
        // ...
        'allow_add' => true,
        'allow_remove' => true,
        'prototype' => true,
        'attr' => array(
            'class' => 'my-selector',
        ),
))

然后,应用给定自定义主题后渲染您的表单

     {% form_theme myForm 'jquery.collection.html.twig' %}
     {{ form(myForm) }}

最后,将以下代码放置在页面底部。

    <script src="{{ asset('js/jquery.js') }}"></script>
    <script src="{{ asset('js/jquery.collection.js') }}"></script>

    <script type="text/javascript">
        $('.my-selector').collection();
    </script>

使用表单主题

大多数情况下,您需要创建一个表单主题,这将帮助您以优雅的方式渲染集合及其子元素。

  • 在您的表单类型中,覆盖getBlockPrefix()方法并返回一个好名字。
// Fuz/AppBundle/Form/AddressType.php

<?php

namespace Fuz\AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class AddressType extends AbstractType
{
    // ...

    public function getBlockPrefix()
    {
        return 'AddressType';
    }
}
  • 在你的表单主题中,你只需要使用相同的名称({% block AddressType_XXX %})。将XXX替换为widgeterrorrow,具体取决于你想做什么(更多信息请参阅Symfony文档)。
{# FuzAppBundle:Advanced:addresses-theme.html.twig #}

{% block AddressType_row %}
<div class="col-md-3">
  {{ form_label(form) }}
  {{ form_errors(form) }}
  {{ form_widget(form) }}
</div>
{% endblock %}

{% block AddressType_widget %}
    {{ form_widget(form) }}
    <br/>
    <p class="text-center">
        <a href="#" class="collection-up btn btn-default">&lt;</a>
        <a href="#" class="collection-remove btn btn-default">-</a>
        <a href="#" class="collection-add btn btn-default">+</a>
        <a href="#" class="collection-down btn btn-default">&gt;</a>
    </p>
{% endblock %}

然后,使用以下方法使用两个表单主题:

     {%
        form_theme myForm
            'FuzAppBundle:Advanced:addresses-theme.html.twig'
            'jquery.collection.html.twig'
     %}

演示网站的高级菜单中有很多使用表单主题的示例,不要犹豫去查看它们。

始终将jquery.collection.html.twig表单主题放在其他你使用的主题下方,以避免设置被覆盖。

使用Doctrine,并在字段中明确存储位置

集合不过是一系列对象,因此默认情况下,此插件会在这个数组中移动元素位置。例如,如果你在你的集合中有A、B和C,并且将B向上移动,它将包含B、A、C。

但是当Doctrine持久化你的集合时,它将保留现有的实体,并简单地更新它们的内容。例如,如果你有一个包含A、B、C的集合,ID分别为1、2和3,你最终会得到一个包含B、A、C的集合,但ID仍然是1、2和3。

在大多数情况下,这不是问题。但是,如果你在每个集合元素上都有其他关联,你永远不应该断开ID和值的链接。你将在数据库表上使用一个位置字段,并管理位置。

例如:

    /**
     * @ORM\Column(name="position", type="integer")
     */
    private $position;

此插件支持这种情况;你需要在你的表单中创建一个position字段(类型为隐藏),并将其映射到你的实体上,并给它一个作为选择器的类。

        $builder->add('position', HiddenType::class, [
            'attr' => [
                'class' => 'my-position',
            ],
        ]);

然后,使用position_field_selector选项将其提供给插件。

    $('.my-selector').collection({
        position_field_selector: '.my-position'
    });

同一页面上有多个集合

如果你想在同一页面上创建多个集合,你需要更改集合前缀,以便插件能够触发正确的操作以针对正确的集合。

例如:

     $('.collectionA').collection({
        'prefix': 'first-collection'
     });

     $('.collectionB').collection({
        'prefix': 'second-collection'
     });

然后,如果你想编辑这些集合的表单主题,例如,你需要在添加按钮上将collection-add替换为first-collection-add

   <a href="#" class="first-collection-add btn btn-default">
       <span class="glyphicon glyphicon-plus-sign"></span>
   </a>

请参阅此示例以获取一个工作示例。

选项

自定义渲染链接演示

你可以通过设置updownaddremoveduplicate选项来自定义显示的链接。

默认值是:

     $('.collection').collection({
         up: '<a href="#">&#x25B2;</a>',
         down: '<a href="#">&#x25BC;</a>',
         add: '<a href="#">[ + ]</a>',
         remove: '<a href="#">[ - ]</a>',
         duplicate: '<a href="#">[ # ]</a>'
     });

你还可以使用以下类:

  • collection-add用于添加按钮
  • collection-remove用于移除按钮
  • collection-up用于向上移动按钮
  • collection-down用于向下移动按钮
  • collection-duplicate用于复制按钮

以及

  • collection-action用于上述任何操作
  • collection-action-disabled与上述相同,但按钮被禁用时(例如,顶部没有“向上”)

请注意,可以使用prefix选项更改collection前缀。

禁用链接演示

你可以通过使用allow_upallow_downallow_addallow_removeallow_duplicate选项来禁用一些按钮。默认情况下,除了duplicate之外的所有按钮都启用。

例如,如果你不希望你的元素可以上下移动,使用:

     $('.collection').collection({
         allow_up: false,
         allow_down: false
     });

如果你使用的是给定的表单主题,allow_addallow_removeallow_duplicate会自动根据你的表单类型配置设置。

设置集合中元素的最小和最大值演示

你可以通过使用min选项来设置集合中允许的最小元素数量。默认情况下,它被禁用(设置为0)。

     $('.collection').collection({
         min: 0
     });

您可以通过使用 max 选项来设置集合中允许的最大元素数量。默认情况下,它设置为 100。

     $('.collection').collection({
         max: 100
     });

您可以使用至少创建的元素数初始化集合(即使它们在数据对象中不存在) (演示)。

     $('.collection').collection({
         init_with_n_elements: 3
     });

底部只有一个添加按钮 (演示)

如果您希望在集合底部只有一个 add 按钮而不是每个集合元素旁边都有一个添加按钮,请使用 add_at_the_end 选项

     $('.collection').collection({
         add_at_the_end: true
     });

自定义添加按钮位置 (演示)

如果您想为添加按钮设置一个特定的位置(不是靠近每个集合元素,也不是在集合底部),则可以使用 custom_add_location 选项。

JS

        $('.collectionA').collection({
            custom_add_location: true
        });

HTML

        <button
            data-collection="collectionA"
            class="collection-action collection-add btn btn-success"
        >Add element to collection</button>

隐藏无用的按钮 (演示)

默认情况下,向上移动 按钮在第一个元素上隐藏,向下移动 按钮在最后一个元素上隐藏。您可以通过将 hide_useless_buttons 设置为 false 来使它们仍然出现。这可能在您想使用 CSS 美化它们时很有用。

     $('.collection').collection({
         hide_useless_buttons: true
     });

事件 (演示)

before_*after_* 选项,允许您在集合中添加、删除或移动元素之前和之后放置回调函数。

  • before_upbefore_downbefore_addbefore_remove 在修改集合之前被调用。如果回调函数返回 false,则修改将被取消,如果返回 trueundefined,则继续进行。

  • after_upafter_downafter_addafter_remove 在修改集合后被调用。如果回调函数返回 false,则修改将被撤销。

  • before_initafter_init 在初始化集合时被调用。不需要返回值。

回调函数接收两个参数

  • collection 引用包含您整个集合的 div(symfony2 字段)

  • element 是已添加(或移动/删除)的集合中的元素

     $('.collection').collection({
         after_add: function(collection, element) {
            // automatic backup or whatever
            return true;
         }
     });

不使用表单主题使用插件 (演示)

表单主题旨在在激活插件时减少所需选项的数量。当您处理表单集合的集合时,这非常有用。但您也可以手动进行,使用以下等效项。

    $('.my-selector').collection({
        prototype_name: '{{ myForm.myCollection.vars.prototype.vars.name }}',
        allow_add: false,
        allow_remove: false,
        name_prefix:  '{{ myForm.myCollection.vars.full_name }}'
    });

请注意,只有 name_prefix 选项是必需的,所有其他选项都有默认值。

淡入 & 淡出支持 (演示)

默认情况下,在添加或删除元素时,fade 动画会使元素移动更平滑。您仍然可以通过使用 fade_infade_out 选项来禁用此选项。

    $('.my-selector').collection({
        fade_in: true,
        fade_out: true
    });

拖 & 放支持 (演示)

如果您正在使用 Jquery UI 并在您的应用程序中有可用的 sortable 组件,则 drag_drop 选项将自动启用,并允许您使用拖 & 放来更改元素位置。您可以通过显式将 drag_drop 选项设置为 false 来禁用此行为。

如有需要,您可以通过使用drag_drop_options选项,通过覆盖传递给jQuery.ui.sortable的选项来自定义sortable

默认情况下,您的集合使用以下选项初始化

     $('.collection').collection({
         drag_drop: true,
         drag_drop_options: {
            placeholder: 'ui-state-highlight'
         }
     });

请注意,您不应覆盖startupdate回调函数,因为它们由该插件使用,有关详细信息,请参阅下面的高级使用中的drag_drop_startdrag_drop_update选项。

更改子选择器

默认情况下,Symfony将集合的每个元素写入位于集合本身下面的div中。因此,此插件将> div视为获取集合元素的默认值。但是,您可能需要将集合的每个元素显示在表中,因此您可以更改此值。

     $('.collection').collection({
        elements_selector: '> div'
     });

您可以使用> trthead > tr或更具体地使用tr.item或仅使用.item(如果您的项目表单主题的顶部设置了class="item")。目标是无论标记如何都能引用集合中的每个项目。

更改父选择器

为了能够将元素添加到集合中,此插件应该知道将包含它们的dom对象。

默认情况下,您的集合元素将位于您的集合下方,例如

    <div id="collection">
       <div id="child_0">(...)</div>
       <div id="child_1">(...)</div>
       <div id="child_2">(...)</div>
    </div>

但是,您可能需要将元素放置在DOM中更深的位置,例如当您在表中放置元素时

    <table id="collection">
        <tbody>
            <tr id="child_0">(...)</tr>
            <tr id="child_1">(...)</tr>
            <tr id="child_2">(...)</tr>
        </tbody>
    </table>

在此示例中,父选择器应为table.collection tbody

请注意,您可以在elements_parent_selector中使用%id%,它将被自动替换为集合的ID。这在处理嵌套集合时尤其有用。

示例

     $('.collection').collection({
        // ...
        children: [{
            // ...
            elements_parent_selector: '%id% tbody'
        }]
     });

默认值

     $('.collection').collection({
        elements_parent_selector: '%id%' // will be the collection itself
     });

不要更改字段名称

Symfony使用字段名称对集合进行排序,而不是每个元素在DOM中的位置。因此,默认情况下,如果您在中间删除一个元素,所有后续元素将减少索引1(field[3]将变为field[2],依此类推),如果您在中间添加一些元素,所有后续元素将看到它们的索引增加以为新元素腾出空间。

使用此实现,您在点击“向上移动”和“向下移动”等操作时可以确保保持正确的位置。但在某些情况下,您可能不希望覆盖索引,最可能是为了维护Doctrine关系。

preserve_names选项设置为true以从不触摸字段名称。但请注意,此选项将禁用allow_upallow_downdrag_drop选项并将add_at_the_end设置为true。

默认值

     $('.collection').collection({
        preserve_names: false
     });

更改操作容器标签

默认情况下,没有表单主题,所有操作都放在一个<div>中。您可以通过设置action_container_tag选项来覆盖此设置,例如,如果您想将操作放在一个<td>中。

默认值

     $('.collection').collection({
        action_container_tag: 'div'
     });

高级使用

更改操作的顺序演示

默认情况下

  • add向上移动向下移动remove按此顺序位于每个集合元素的下方
  • 使用add_at_the_bottom选项可以将add按钮放在集合的底部

您可以通过在表单主题的任何位置手动创建按钮来更改这些按钮的位置。

只要具有一个操作类,您就可以使用任何自定义可点击元素

  • collection-add用于add按钮
  • collection-remove用于remove按钮
  • collection-up用于move up按钮
  • collection-down用于move down按钮

警告collection来自prefix选项:如果您更改插件的prefix,您也应该更改此类。

示例

如果我们有一组文本字段,并且想要在每个值右侧而不是下方显示操作,我们将使用类似以下的方法

{% block MyType_label %}{% endblock %}
{% block MyType_errors %}{% endblock %}

{% block MyType_widget %}

    <div class="row">
        <div class="col-md-8">
            {{ form_widget(form.value) }}
        </div>
        <div class="col-md-2">
            <a href="#" class="collection-up btn btn-default">Move up</a>
            <a href="#" class="collection-down btn btn-default">Move Down</a>
        </div>
        <div class="col-md-2">
            <a href="#" class="collection-remove btn btn-default">Remove</a>
            <a href="#" class="collection-add btn btn-default">Add</a>
        </div>
    </div>

{% endblock %}

注意:在启用插件时,不要忘记设置 add 选项,因为如果您的集合被清空,插件将根据插件的配置生成一个 add 按钮。

提示:当 add 按钮被放入集合的元素中时,会在点击的元素旁边创建一个新的元素,而不是在集合的末尾。

高级拖放支持 (演示)

如果您需要在您的集合中监听来自 jQuery.ui.sortablestart 和/或 update 事件,您不应该在 drag_drop_options 中覆盖 startupdate 选项,而应该使用内置的 drag_drop_startdrag_drop_update 选项。

     $('.collection').collection({
         drag_drop_start: function (event, ui, elements, element) {
            // ...
         },
         drag_drop_update: function (event, ui, elements, element) {
            // ...
         }
     });

注意

  • eventui 来自 jQuery.ui.sortablestart 回调。
  • elements 包含受影响的集合中所有的元素
  • element 是集合中移动的元素
  • 如果您的回调返回 false,则位置更改将被取消/撤销。

集合的集合 (演示)

此插件具有管理表单集合集合的能力,但为了避免冲突,您应该

在您的表单类型中

  • 为每个集合设置一个唯一的 prototype_name 选项和选择器类
    ->add('collections', 'collection',
       array (
            'type' => 'collection',
            'label' => 'Add, move, remove collections',
            'options' => array (
                    'type' => 'text',
                    'label' => 'Add, move, remove values',
                    'options' => array (
                            'label' => 'Value',
                    ),
                    'allow_add' => true,
                    'allow_remove' => true,
                    'prototype' => true,
                    'prototype_name' => '__children_name__',
                    'attr' => array (
                            'class' => "child-collection",
                    ),
            ),
            'allow_add' => true,
            'allow_remove' => true,
            'prototype' => true,
            'prototype_name' => '__parent_name__',
            'attr' => array (
                    'class' => "parent-collection",
            ),
    ))

在插件选项中

  • 使用一个唯一的集合前缀,因此点击集合的 add 按钮将向正确的集合添加一个项目

  • children 选项的 selector 属性中定义子选择器(必须选择子集合的根节点)

     $('.parent-collection').collection({
         prefix: 'parent',
         children: [{
             selector: '.child-collection',
             prefix: 'child'
             // ...
         }]
     });