Уменьшить список выбора в выпадающем списке select2 (при поиске) - PullRequest
0 голосов
/ 06 ноября 2018

Когда я использую select2, список выбора не уменьшается при поиске, что довольно раздражает, когда у меня более 50 вариантов выбора.

Я использую фреймворк symfony4 с маршрутом, предоставляющим мои теги, которые находятся в БД:

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

Затем я запускаю свой select2 с этим кодом, предоставленным плагином symfony Tags :

$( 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);
            }
        });
    }
}

Вот результат на моей веб-странице перед поиском: enter image description here

Вот после поиска: enter image description here

Как видите, список все тот же, только результат подчеркнут. Я хотел бы отфильтровать результат в зависимости от того, что я ищу, поэтому мне не нужно полностью прокручивать, пока я не найду подчеркнутый термин.

Поскольку это базовая работа Select2 , я полагаю, в моем JS есть проблема с конфигурацией.

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Просто базовый пример с некоторым кодом, чтобы показать, как мы используем 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 );
}

РЕДАКТИРОВАТЬ после вашего последнего комментария

Это значение недопустимо

Это потому, что ваше значение не является частью выбора, когда формуляр добавляет поле. Вы должны добавить addEventListener на PRE_SUBMIT, чтобы динамически добавить это значение. Вы можете сделать это следующим образом:

// 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);
    }
);

Как я сказал в начале, если у вас нет столько тегов, и они не развиваются регулярно, вы можете создать свой выбор со всеми вашими тегами и избежать всей Ajax-части JavaScript-кода Select2! (Я думаю, это будет проще и достаточно для вашего случая)

0 голосов
/ 06 ноября 2018

Я установил это значение при загрузке:

let currentSearch = false;

Затем я изменил раздел «AJAX» моего JS, чтобы он зацикливался на списке с искомым значением:

        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
                };
            }
        },

Я почти уверен, что есть более чистый / простой способ сделать это, но на данный момент это быстрое исправление.

...