Twitter Typeahead.js — удалить датум при выборе

Я использую typeahead.js 0.9.3, и он работает плавно. Мой вопрос заключается в том, можно ли удалить датум из набора данных по событию "typeahead:selected" (или любому событию, если на то пошло).

Я извлекаю данные из набора данных, используя параметр Typeahead prefetch при загрузке страницы. Я знаю, что мог бы вызвать $('selector').typeahead('destroy') и повторно инициализировать typehead и использовать filter в объекте prefetch, но мне кажется довольно тяжело вызывать данные снова и снова (мы не кэшируем данные в локальном хранилище).

Я полагаю, что ищу что-то похожее на функцию filter для перебора массива данных и удаления ранее выбранных (или всех выбранных) данных. Не похоже, что в typeahead есть общедоступная функция для этого, но, возможно, я ее пропустил.

Я прочитал документы typeahead и искал здесь, но не нашел ответа.

РЕДАКТИРОВАТЬ: я решил непосредственную проблему, переключившись с prefetch на local и используя вызов AJAX post для получения данных, установил его как глобальную переменную, а затем передал ее в typeahead, где я могу добавлять/удалять элементы из глобального массива данных а затем уничтожить/повторно инициализировать ввод по мере необходимости. Далеко от идеала, но работает.


person rpmartz    schedule 10.01.2014    source источник
comment
Почему бы просто не отфильтровать данные перед передачей их в typehead?   -  person Cory Danielson    schedule 10.01.2014
comment
Потому что нет механизма повторной фильтрации без вызова .typeahead('destroy') и повторной инициализации typeahead другим вызовом prefetch. Я не хочу POST после любого typeahead:selected события.   -  person rpmartz    schedule 11.01.2014


Ответы (3)


Как вы указали, это сложно, если не невозможно, без массового взлома текущей версии typeahead. Есть 3 вещи, которые вам нужны:

  1. Удаленный как вариант функции (где вы реализуете свою собственную функцию получения, которая получает доступ к вашим данным, фильтрует запрос и удаляет уже выбранные вами элементы.
  2. Управление кешем: возможность запретить управление вводом текста, чтобы использовать кеш для последнего выполненного поиска предложения.
  3. Поиск предложений по запросу, обновляйте результаты предложений только тогда, когда они вам нужны (когда вы входите в поле ввода и начинаете вводить запрос).

Следующая версия typeahead (0.10 в настоящее время находится в разработке) может поддерживать необходимые функции.
Но... так получилось, что мой (Svakinn) форк typeahead поддерживает все три необходимых вам условия. Ваша конфигурация должна предоставлять функцию получения, в которой вы выбираете данные из ваших данных инициализации и фильтруете их по строке запроса и уже выбранным параметрам.

remote: yourGetterFunction

Затем вам нужно отключить кеш предложений:

skipCache: true

Если вы не хотите ждать следующего релиза typeahead, я предлагаю вам попробовать его:
https://github.com/Svakinn/typeahead.js/tree/typeaheadSimple Также доступны живые живые примеры JQuery и Knockout:
https://github.com/Svakinn/typeahead.js/blob/typeaheadSimple/Examples.md

person Svakinn    schedule 14.01.2014
comment
Это выглядит великолепно - сейчас я тестирую ваше решение. - person David Robbins; 06.02.2014

Вы можете использовать эту функциональность в Typeahead 0.10 для любого набора данных Bloodhound, будь то удаленный, предварительно выбранный или локальный.

Просто отслеживайте, какие данные были выбраны независимо от набора данных Bloodhound, и не используйте Bloodhound#ttAdapater() в качестве источника опережающего ввода. Метод ttAdapter — это просто оболочка для Bloodhound#get(query, cb), поэтому вместо него вызывайте get(query, cb) напрямую с помощью пользовательского обратного вызова, который проверяет каждое предложение на соответствие текущим выборам.

Вот JSFiddle — http://jsfiddle.net/likeuntomurphy/tvp9Q/

var selected = [];

var select = function(e, datum, dataset) {
    selected.push(datum.val);
    $("#selected").text(JSON.stringify(selected));
    $("input.typeahead").typeahead("val", "");
}

var filter = function(suggestions) {
    return $.grep(suggestions, function(suggestion) {
        return $.inArray(suggestion.val, selected) === -1;
    });
}

var data = new Bloodhound({
    name: 'animals',
    local: [{ val: 'dog' }, { val: 'pig' }, { val: 'moose' }],
    datumTokenizer: function(d) {
      return Bloodhound.tokenizers.whitespace(d.val);
    },
    queryTokenizer: Bloodhound.tokenizers.whitespace,

    // custom suggestion filter is applied after Bloodhound
    // limits the set of possible suggestions
    // see comment by Basti below
    limit: Infinity
});

data.initialize();

$('input.typeahead').typeahead(null,
    {
        name: 'animals',
        displayKey: 'val',
     /* don't use
        source: data.ttAdapter(), */
        source: function(query, cb) {
            data.get(query, function(suggestions) {
                cb(filter(suggestions));
            });
        },
        templates: {
            empty: '<div class="empty-message">No matches.</div>'
        }
    }
).bind('typeahead:selected', select);
person likeuntomurphy    schedule 01.07.2014
comment
Это работало фантастически. Я довольно долго искал решение этой проблемы (я не хотел полностью очищать кеш для каждого события ввода, когда я знаю, что в моем удаленном источнике больше нет результатов). Отличный ответ! :) - person dave; 31.07.2014
comment
Одно важное дополнение: вы также должны установить параметр ограничения для Bloodhound на что-то очень большое или даже на бесконечность, потому что ограничение на предложения применяется до вызова вашего пользовательского фильтра. Наихудший сценарий: из 100 возможных результатов вы бы отфильтровали 5 с помощью своего пользовательского фильтра, но Bloodhound дает вам только эти 5 из-за предела предложений, что приводит к пустому результату. - person Basti; 15.08.2014
comment
Отличный улов! Я еще не использовал Bloodhound с достаточно большим набором данных, чтобы было необходимо ограничение. - person likeuntomurphy; 16.08.2014
comment
Определенно лучшее решение, чем принятое решение. - person PW Kad; 05.11.2014
comment
Просто небольшое обновление, вместо использования jQuery val они рекомендуют использовать $('.typeahead').typeahead('val', myVal);, потому что похоже, что в текущей версии он немного ломается. github.com/twitter/typeahead.js/ блоб/мастер/документ/ - person Tom Prats; 05.03.2015
comment
Спасибо за это предложение, оно сработало! Но имейте в виду, что в текущей версии Bloodhound (0.11.1) вы должны использовать data.search вместо data.get, чтобы получить список совпадающих предметов. Также имейте в виду, что suggestion.val в приведенной выше функции filter обращается к свойству val значений источника данных Bloodhound. Если у вас есть какое-либо другое свойство для хранения ваших данных, вам нужно будет адаптировать это (это может быть ошибкой новичка, но тем не менее мне потребовалось несколько минут, чтобы найти его) - person DHainzl; 24.09.2015

попробуйте это, это работа для меня.

$('#selector').typeahead('setQuery', "");
person syarif    schedule 15.01.2014
comment
Все, что нужно сделать, это очистить запрос. Это не влияет на массив datums... вызов .typeahead('setQuery',"") не очищает выбранные элементы. - person rpmartz; 15.01.2014