jQuery UI Автозаполнение с гибридным поиском текста / идентификатора - PullRequest
11 голосов
/ 21 июля 2010

У меня много проблем с работой виджета автозаполнения jQuery.Я использую список пар ключ / значение с сервера.

У меня есть следующие требования:

Если пользователь выбирает значение из виджета, я хочу передать идентификатор на сервер.

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

Предположим, что someAjaxFunction возвращает массив объектов, ожидаемых виджетом автозаполнения: {label:label, value:key}.

Изначально я настроил виджет автозаполнения следующим образом:

$(input).autocomplete({
    source: sourceFunction,
    minLength: 1
});

Изменение выделения даже при наведении курсора на один из элементов изменяет текст в текстовом поле, на который ссылается $ (ввод), на основной ключ, а не на метку.Это крайне нежелательно с точки зрения взаимодействия с пользователем - на самом деле, причина, по которой я это расследую, заключается в том, что пользователи сайта, который я создаю, были постоянно сбиты с толку текстом, который они вводили, по-видимому, превращаясь в случайные числа!

Я добавил скрытое поле под текстовым полем и реализовал события select () и focus (), чтобы скрыть идентификатор следующим образом:

$(input).autocomplete({
    source: sourceFunction,
    minLength: 1
    focus: function(event, ui) {
        $(idField).val(ui.item.value);
        $(this).val(ui.item.label);
        return false;
    },
    select: function(event, ui) {
        $(idField).val(ui.item.value);
        $(this).val(ui.item.label);
        return false;
    },
    minLength: 1
});

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

В документации по автозаполнению пользовательского интерфейса jQuery перечислено событие change и указано, что свойство item аргумента ui будет установлено для выбранного элемента.Я подумал, что могу сбросить скрытое поле идентификатора при нажатии клавиши и повторно заполнить идентификатор, если автозаполнение изменилось.К сожалению, в дополнение к событию нажатия клавиш, захватывающему целую кучу нажатий клавиш, которые не должны сбрасывать идентификатор, оператор return false в вышеупомянутом событии select, который необходим для управления текстом в текстебокс не позволяет событию change правильно назначить ui.item.

Так что теперь я застрял - я не знаю, что еще я могу попытаться сделать так, чтобы виджет поддерживал функциональность так, как кажетсядолжен поддерживать по умолчанию.Либо этот процесс намного сложнее, чем должен быть, или я упускаю что-то действительно очевидное.Я просмотрел все доступные события и все примеры и пришел с пустыми руками.Фактически, даже пример «Пользовательские данные и отображение» на странице пользовательского интерфейса jQuery страдает от этой проблемы.

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

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

Ответы [ 4 ]

2 голосов
/ 27 июля 2010

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

Ссылка и интервал оформлены таким образом, что они выглядят как кнопка с буквой X и имеют обработчик события щелчка для удаления записи из DOM, очистки скрытого поля и повторного отображения поля ввода при нажатии. Поэтому, когда элемент выбран:

  <div class="container">
    <a href="#"><span>Selected Item</span></a>
    <input id="myautocomplete" type="text" />
    <input type="hidden" name="myvalue" value="1" />
  </div>

А когда элемент не выбран:

 <div class="container">
    <input id="myautocomplete" name="myautocomplete" type="text" />
    <input id="myvalue" name="myvalue" type="hidden" value="" />
  </div>

Таким образом, вы либо вынуждены выбрать элемент, либо вводите текст произвольной формы. С другой стороны, если параметр запроса с ключом «myvalue» пуст, то вы бы лучше посмотрели на параметр запроса с ключом «myautocomplete».

1 голос
/ 01 января 2012

Когда я предполагаю, что у вас установлены следующие поля:

<div>
    <input type="text" name="visible" class="autocomplete-reference" />
    <input type="hidden" name="hidden" />
</div>

Вам нужно инициировать следующие js (это работает с jQuery 1.5.2):

$(document).ready(function() {
    $('.autocomplete-reference').each(function () {
        $(this).keydown(function(e){
            /*
            * this will reset hidden id reference on each visible field manual change
            * we have to bind it on keydown because we want to recognize event of submiting form by enter after autocomplete set
            */
            if (e.keyCode != 13) {
                $(this).siblings('input[type=hidden]').each(function () {
                    $(this).val('');
                });
            }
        });
        $(this).autocomplete({
            minLength: 1,
            /* you can set appending of autocomplete menu into some container to set css contextually
            appendTo: '#someElem',*/
            source: sourceFunction,
            search:function (event, ui) {
                //TODO ...spinner init...
            },
            open:function (event, ui) {
                /* you can grab autocomplete menu widget by this to manipulate some recognizing id, etc..
                 * $(this).autocomplete('widget')
                */
                //TODO ..stop spinner ...
                $(this).keydown(function(e){
                    /* this is important for live reference updates while arrow keys changes  */
                    if (e.keyCode == 37 || e.keyCode == 39) {
                       $($(this).data('autocomplete').menu.active).find('a').trigger('click');
                    }
                });
            },
            focus: function(event, ui) {
                /* here we'll map our data object onto both fields */
                $(this).val(ui.item.label);
                $(this).siblings('input[type=hidden]').each(function () {
                    $(this).val(ui.item.key);
                });
            },
            select: function(event, ui) {
                /* here we'll map our data object onto both fields */
                $(this).val(ui.item.label);
                $(this).siblings('input[type=hidden]').each(function () {
                    $(this).val(ui.item.key);
                });
            },
            close: function(event, ui) {
                //TODO ..stop spinner ...
            }
        });
    });
});

Очень приятно иметь некоторую проверку на стороне сервера, которая может преобразовывать точные: видимые значения полей в ссылки для быстрого набора текста.

0 голосов
/ 28 декабря 2014

Вы можете использовать event.preventDefault

Собрать выбранные значения через ui.item.label или ui.item.value, получить необходимое значение и установить его в том же текстовом поле.

var idNameCombo = ui.item.label;
            event.preventDefault();
            $("#mID").val(idNameCombo.split(",")[0].trim());
0 голосов
/ 07 декабря 2012

Хотя это старый вопрос, мой метод может помочь.

При .change событии вы можете искать значение текстового поля по значению из вашего списка источников, используя цикл.

Перейти к более подробной информации: здесь это в списке источников Ajax, но тренировки похожи. Поиск текста в интерфейсе автозаполнения Jquery

Эта вещь беспокоила меня много раз, и в конце концов теперь я понял:)

...