【问题标题】:Reduce choice list in select2 dropdown (when searching)减少 select2 下拉列表中的选择列表(搜索时)
【发布时间】:2018-11-06 13:11:56
【问题描述】:

当我使用 select2 时,搜索时选项列表并没有减少,当我有超过 50 个选项时,这很烦人..

我使用 symfony4 框架,路由提供我在数据库中的标签:

/**
 * @Route("/miseenpage/keywords.json", name="keywords", defaults={"_format": "json"})
 */

然后我用symfony Tags plugin提供的代码初始化我的select2:

$( document ).ready(function() {
    initTags($('input[name$="[tagsText]"]'));
});

// TAGS
function initTags($input) {
    if($input.length) {
        $input.attr('type', 'hidden').select2({
            width: '85%',
            tags: true,
            tokenSeparators: [","],
            createSearchChoice: function (term, data) {
                if ($(data).filter(function () {
                    return this.text.localeCompare(term) === 0;
                }).length === 0) {
                    return {
                        id: term,
                        text: term
                    };
                }
            },
            multiple: true,
            ajax: {
                url: $input.data('ajax'),
                dataType: "json",
                data: function (term, page) {
                    return {
                        q: term
                    };
                },
                results: function (data, page) {
                    return {
                        results: data
                    };
                }
            },
            initSelection: function (element, callback) {
                var data = [];

                function splitVal(string, separator) {
                    var val, i, l;
                    if (string === null || string.length < 1) {
                        return [];
                    }
                    val = string.split(separator);
                    for (i = 0, l = val.length; i < l; i = i + 1) {
                        val[i] = $.trim(val[i]);
                    }
                    return val;
                }

                $(splitVal(element.val(), ",")).each(function () {
                    data.push({
                        id: this,
                        text: this
                    });
                });
                callback(data);
            }
        });
    }
}

这是我搜索前网页中的结果:

搜索后如下:

如您所见,列表仍然相同,只是结果带有下划线。我想根据我搜索的内容过滤结果,所以在找到带下划线的术语之前,我不必一直滚动。

因为这是Select2的基本工作,我猜我的JS有配置问题。

【问题讨论】:

  • 嗨,可能是一个愚蠢的问题,但你为什么要在输入类型 hidden 上初始化你的 select2 ? (确保您正在初始化好的输入)。顺便说一句,一个好的做法是在输入至少 X 个字符后加载结果(以避免多次查询您的服务器)。与您想要做的相比,您的 JS 看起来真的很复杂...
  • 我使用了 symfony 的标签插件中的 cookbook,所以我没有编辑代码,因为我的行为应该与常规 select2 相同?除了列表没有减少之外,一切都运行良好
  • 这看起来太复杂了(我们在所有项目中都使用了很多 nativ select2)。您使用的是哪个版本的 Select2?你能调试你的关键字函数,看看你是否真的得到了用户在字段中输入的内容吗?
  • 使用 select2 v3.5.3。因为它是一个应该填充的选择(数据库中的对象),所以它在加载时已经可以有一些值(我认为这是从常规 select2 添加的代码的一部分)。我找到了一种解决方法,很确定它不是正确的,但可以工作。我在下面发布代码。
  • 已经加载的值是用initSelection 部分设置的。如果它足以满足您的需求(可能只有 50 个值),您应该删除所有 ajax 部分。如果不是(如果您必须从 DB 动态加载对象),请告诉我,我会尽力帮助您。

标签: javascript symfony jquery-select2


【解决方案1】:

我在加载时实例化了这个值:

let currentSearch = false;

然后我更改了我的 JS 的“AJAX”部分,因此它使用搜索值循环列表:

        ajax: {
            url: $input.data('ajax'),
            dataType: "json",
            data: function (term) {
                currentSearch = term;
                return {
                    q: term
                };
            },
            results: function (data) {
                let returnTab = [];
                data.forEach(function(e) {
                    if(e.text.includes(currentSearch)){
                        returnTab.push(e);
                    }
                });
                return {
                    results: returnTab
                };
            }
        },

我很确定有一种更清洁/更简单的方法可以做到这一点,但目前它是一个快速修复。

【讨论】:

    【解决方案2】:

    只是一个基本示例,其中包含一些代码来展示我们如何将 Select2(v4.0.3,3.5 可能完全不同)与 Ajax 一起使用

    在树枝上,例如:

    $("#users").css('width', '100%').select2({
                minimumInputLength: 3,
                ajax: {
                    url: "{{ path('api_search_user') }}",
                    dataType: 'json',
                    delay: 500,
                    data: function (params) {
                        return {
                            needle: params.term // Here we send user input to the controller
                        };
                    },
                    processResults: function (data) {
                        return {
                            results: data
                        };
                    },
                    cache: false
                }
            });
    

    我们有一个控制器,它具有搜索用户的功能:

    /**
     * @Route("/search_users", name="api_search_users")
     * @param Request $request
     * @return JsonResponse
     */
    public function searchUsersAction(Request $request)
    {
        $needle = $request->get('needle'); // Here we retrieve user input
        $users = $this->get(User::class)->searchUsers($needle);
        return new JsonResponse($users );
    }
    

    编辑在您上次评论之后

    此值无效

    这是因为当表单生成器添加字段时,您的值不是选择的一部分。您必须在PRE_SUBMIT 上添加addEventListener 才能动态添加此值。你可以这样做:

    // Define form modifier
    $usersFormModifier = function (FormInterface $form, $users) use ($options) {
        $choices = array();
        if(is_array($users)) {
            $choices = $users;
        }
    
        $form->add(
            'users',
            EntityType::class,
            array(
                'label' => 'conversation.form.users',
                'multiple' => true,
                'class' => 'AppBundle\Entity\Security\User',
                'choices' => $choices,
                'choice_label' => function (User $user) {
                    return $user->getLastName() . " " . $user->getFirstName();
                },
                'attr' => array(
                    'placeholder' => 'default.search_person'
                )
            )
        );
    };
    
    // On PRE_SET_DATA, we load users from our object (which only contains their IDs)
    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function (FormEvent $event) use ($usersFormModifier) {
            $usersFormModifier($event->getForm(), $event->getData()->getUsers()->toArray());
        }
    );
    
    // On PRE_SUBMIT, we add the options, so the select will accept newly added values
    $builder->addEventListener(
        FormEvents::PRE_SUBMIT,
        function (FormEvent $event) use ($usersFormModifier) {
            $data = $event->getData();
    
            $users = null;
            if(isset($data['users'])) {
                $users = $this->entityManager->getRepository('AppBundle:Security\User')->findBy(array('id' => $data['users']));
            }
    
            $usersFormModifier($event->getForm(), $users);
        }
    );
    

    正如我一开始所说,如果你没有那么多标签,而且它们没有定期演变,你可以用你所有的标签来构造你的选择,并避免 Select2 javascript 代码的所有 Ajax 部分! (我认为这对你的情况会更容易和足够)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-22
      • 1970-01-01
      相关资源
      最近更新 更多