Как использовать кнопку в раскрывающемся списке автозаполнения для дальнейшей фильтрации уже отображаемых результатов - PullRequest
5 голосов
/ 17 января 2020

Я ввел окно поиска автозаполнения на моем asp. net mvc4 сайте. В настоящее время я могу получить окно, возвращающее результаты, которые обновляются при вводе в поле поиска. Я также динамически генерирую кнопки «категории» на основе «идентификаторов типов» результата и вставляю их в заголовок, который появляется, когда автозаполнение дает результаты.

Я хочу представить функциональность, которая выглядит следующим образом: когда пользователь при нажатии на кнопку категории существующие результаты автозаполнения будут отфильтрованы, поэтому будут показаны только результаты с таким «идентификатором типа». После этого, если пользователь хочет снова увидеть все результаты, соответствующие строке поиска, он может нажать кнопку «Все».

Чтобы увидеть рабочую версию этого, проверьте поле поиска на Discogs. .com. Я также вставил скриншот этого виджета ниже, для справки.

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

enter image description here

Мой код приведен ниже. В нем у меня уже есть работающее автозаполнение, и у меня есть часть, которая динамически генерирует кнопки категорий. Теперь мне нужна помощь в поиске шаблона проектирования для дальнейшей фильтрации результатов автозаполнения при нажатии динамически генерируемых кнопок категорий.

Ответы [ 3 ]

3 голосов
/ 23 января 2020

Вы запрашиваете шаблон проектирования, поэтому вот один из них:

  • сохранить категорию как пользовательский атрибут данных внутри кнопок заголовка:

    //generate the category buttons within the header
    for (var i = 0; i < arrayLength; i++) {
      header += '<button type="button" data-category="' + uniqueCategories[i] + '" ';
      header += 'class="btn btn-default btn-xs">Category' + uniqueCategories[i] + '</button>'
    

    Для кнопки showAll просто установите пустой атрибут:

    <button type="button" class="btn btn-default btn-xs" data-category>All</button>

  • внутри функции _renderItem сохраните категорию для каждого элемента списка:

    return $('<li data-category="' + item.objectType + '">')

После этого Вы можете использовать делегирование событий для фильтрации элементов списка:

  1. установить отображение: блок для всего списка items
  2. set display: нет для несоответствующих элементов списка

Если вы установите стили в строгом l oop, будет просто только одна перерисовка * в браузере:

// this function can be further optimized
function applyFilter(c) {
  $("li[data-category]").show().each(function() {
    if(c && c != $(this).data("category")) {
      $(this).hide();
    }
  });
}

$(document).on("click", ".btn[data-category]", function(e){
  // category shall be undefined to show all items, otherwise 1,2, and so on
  applyFilter($(this).data("category"));
})

Не стесняйтесь спрашивать более подробную информацию, но я верю, Вы поймете идею.

(*) Гарантируется ли отрисовка DOM для блокировки во время выполнения одной (синхронной) функции?

2 голосов
/ 27 января 2020

Вызовите бэкэнд API, получите результаты автозаполнения и поместите их в массив. Я предполагаю, что эту функциональность здесь не нужно писать (если вам нужна помощь, пожалуйста, дайте мне знать). Если у вас есть массив с вашими результатами, вы можете использовать https://www.w3schools.com/jsref/jsref_filter.asp

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

var ages = [32, 33, 12, 40];

function checkAdult(age) {
  return age >= document.getElementById("ageToCheck").value;
}

function myFunction() {
  document.getElementById("demo").innerHTML = ages.filter(checkAdult);
}

.filter использует функцию checkAdult для возврата только тех элементов в массиве, которые больше, чем ageToCheck. Здесь вы можете легко реализовать logi c для локальной фильтрации ваших результатов, чтобы предотвратить повторные обращения к бэкэнду.

Надеюсь, это поможет! Если вам нужна дополнительная информация, дайте мне знать. :)

Учитывая ваш комментарий:

Вроде да. У меня работает функция автозаполнения, и у меня также есть динамическое создание кнопок фильтра в рамках работы автозаполнения. Теперь мне нужно выяснить, как скрыть / удалить результаты автозаполнения, которые не соответствуют ui.item.objectType, связанному с соответствующей кнопкой фильтра. кстати, этот вопрос не имеет ничего общего с java. скрипт, который вы видите выше, это javascript / jquery / ajax

, это именно то, что нужно.

2 голосов
/ 23 января 2020

Как вы сами себе предложили, на самом деле лучший способ - сохранить в кэше результаты поиска автозаполнения и выполнять дальнейшую фильтрацию локально. У меня нет опыта работы с AJAX или Javascript, но я могу привести примеры некоторых простых понятий в C#, которые могут вам в этом помочь.

Для начала, я вижу, в вашем коде у вас есть метод для сделать автозаполнение поиска. Кажется, вы часто используете лямбда-выражения, однако вы можете извлечь из них именованные методы. Я хотел бы, чтобы метод поиска автозаполнения возвращал массив объектов, содержащих результаты сопоставления. Как я уже сказал, незнаком с AXAJ, но в ASP. NET есть кое-что, что вы должны отметить при сохранении локальных временных данных. Один из них - цикл страницы, другой - постоянство переменной. Я предполагаю, что вы знакомы с вашей средой и знаете, как правильно хранить данные, чтобы они правильно сохранялись на протяжении всей жизни страницы. Я бы использовал для этого переменную сеанса.

У вас может быть функция фильтрации, которая будет выглядеть примерно так:

// For the sake of comprehensability, let's assume your result object type is called ACResult, and ACResult.ObjectType is an integer as a type ID.
internal ACResult[] FilterResults(int objType)
{
    return cachedResults.Where((result) => { return result.ObjectType == objType; }).ToArray();
}

В примере выше, cachedResults предполагается, что это массив с вами элементы результатов поиска. Он использует метод расширения LINQ Where<T>(Func<T, bool> predicate). Здесь есть метод ToArray<T>(), поскольку метод Where вернет IEnumerable, который необходимо преобразовать обратно в массив, чтобы соответствовать типу возвращаемого метода. LINQ или другой эквивалент может быть недоступен. Более простой альтернативой является перебирать их и выбирать те, которые соответствуют желаемому типу:

internal ACResult[]  FilterResults(object objType)
{
    List<ACResult> ret = new List<ACResult>();
    foreach (ACResult result in cachedResults)
    {
        if (result.ObjectType == objType)
            ret.Add(result);
    }
    return ret.ToArray();
}

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

void CategoryButton_OnClicked(int objType)
{
    ACResult[] matchingCategory = FilterResults(objType);
    if (objType != -1) // Assuming -1 means it's your "All" button.
    {
        //Pseudo function encapsulating your suggestion list rendering:
        ReRenderSuggestionList(matchingCategory);
    }
    else
    {
        //Your "All" button clears the cat filtering without reloading the results, which is why the FilterResults method doesn't alter the original "cachedResults" array.
        ReRenderSuggestionList(cachedResults);
    }
}

Это может не сильно помочь, но я действительно пытаюсь помочь вам здесь. Меня интригует, как что-то, что может быть тривиально в одних средах, может превратиться в настоящую проблему в других, особенно в веб-приложениях, поэтому, вероятно, я держусь от них подальше. Я занимаюсь WinForms, библиотеками классов (. NET (Framework | Core | Standard)) и приложениями UWP.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...