Программно добавить новую опцию jquery-select2-4 и сбросить поле поиска?

Я использую jquery-select2-4 для поиска во внешней базе данных и предоставления пользователю результатов поиска, которые он может Выбери из.

У меня есть рабочая версия, работающая на этом jsfiddle.

Но если, например, возвращается только 1 результат поиска, я хочу пропустить весь процесс выбора и просто добавить возвращенный результат поиска в список выбранных параметров. В соответствии с документами select2 я могу добавить новый параметр, подобный этому:

option = new Option("Sample text", "123", true, true);
select2_element.append(option);
select2_element.trigger('change');

Кажется, это работает до некоторой степени. Но есть несколько проблем.

  • Я не могу очистить поле поиска при добавлении опции.
  • Я не могу добавить ничего, кроме id и text.
  • Добавленная опция отображается пользователю как undefined.

Я понимаю, что этот вопрос содержит 3 аспекта, но все 3 аспекта, вероятно, относятся к этому 1 вопросу:

Как вы программно добавляете новую опцию jquery-select2-4 и сбрасываете поле поиска?

Для справки, это контекст кода, о котором я спрашиваю:

var formatRepo, formatRepoSelection, selectRepos;

formatRepoSelection = function(element) {
  return element.name + ' ' + element.forks + ' ' + element.id;
};

formatRepo = function(element) {
  var markup;
  if (!element.loading) {
    return markup = element.name + ' ' + element.id;
  }
};

selectRepos = function() {
  var option, select2_element;
  select2_element = $('#select2_element');
  select2_element.select2({
    ajax: {
      url: "https://api.github.com/search/repositories",
      dataType: 'json',
      data: function (params) {
        return {
          q: params.term,
          page: params.page
        };
      },
      processResults: function (data, params) {

        if (data.items.length === 1) {
          // START: The code I am asking about.
          // Add the search result directly as an option.
          option = new Option("Sample text", "123", true, true);
          select2_element.append(option);
          return select2_element.trigger('change');
          // END: The code I am asking about.
        } else {
          params.page = params.page || 1;

          return {
            results: data.items,
            pagination: {
              more: (params.page * 30) < data.total_count
            }
          };
        }
      },
      cache: true
    },

    escapeMarkup: function(markup) {
      return markup;
    },
    templateResult: formatRepo,
    templateSelection: formatRepoSelection
  });
};

$(function() {
  return selectRepos();
});

person Cjoerg    schedule 31.01.2016    source источник
comment
Не видя, как ваш JS используется для инициализации Select2, нельзя ответить на вопросы 2 и 3.   -  person Kevin Brown    schedule 01.02.2016
comment
Это в файле jsfiddl. Я мог бы добавить его к вопросу, если хотите, но я пропустил его, потому что он соответствует стандартной настройке, и я не хотел загромождать вопрос стандартным кодом.   -  person Cjoerg    schedule 01.02.2016
comment
Теперь я добавил контекст кода.   -  person Cjoerg    schedule 02.02.2016


Ответы (1)


Я сделал два изменения в исходном коде:

1. Смоделируйте выбор единственного оставшегося элемента

Как вы указали, создание элемента option имеет свои ограничения: вы можете указать только свойства id и text, не оставляя возможности доступа к другим свойствам выбранного элемента. .

Кроме того, он генерирует неопределенные значения. Это связано с тем, что функция обратного вызова formatRepoSelection пытается получить доступ к свойствам (name и forks), которые не определены для объекта, созданного для элемента option. Вы могли бы попытаться обойти это и использовать в этом случае свойство text, но все равно у вас не было бы решения для вышеупомянутых ограничений.

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

Это имеет непосредственное преимущество в том, что обычное поведение выбора применяется, как если бы пользователь щелкнул элемент, и поэтому он немедленно решает все три проблемы, которые у вас были:

  • текст фильтра очищается автоматически;
  • функция formatRepoSelection получает обычный объект, поэтому метка тега соответствует ожидаемой;
  • вам доступны те же свойства, что и для любого предмета.

Вот код, реализующий это:

    if (data.items.length === 1) {
      // Change 1:
      // Allow the list to update
      setTimeout(function() {
          // ... and then send a click event to the first list item
          // Note the used id has the SELECT id in the middle.
          $("#select2-select2_element-results li:first-child").trigger('mouseup');
      }, 0);

Недостатком этого решения является то, что вы становитесь зависимым от аспекта реализации; будущая версия select2 может организовать результаты по-другому с точки зрения элементов и свойств HTML.

Но обновлять код всякий раз, когда вы решите использовать более новую версию select2, не составит большого труда.

2. Вернуть правильный объект

Ваш код вызвал ошибку в библиотеке select2:

TypeError: b не определено, в select2.min.js:2:9842

Это из-за этого утверждения:

return select2_element.trigger('change');

Это возвращает объект jQuery select2_element, но библиотека ожидает, что возвращаемое значение будет иметь свойство results.

Поскольку этот триггер больше не нужен, это можно исправить, заменив приведенное выше на:

  // Change 2:
  // Return empty results array
  return {
    results: data.items
  };

Не поддавайтесь искушению установить results: [], потому что нам все еще нужно, чтобы элемент был там, чтобы имитировать событие мыши.

И... это все.

Вот рабочее решение: JS fiddle.

person trincot    schedule 09.02.2016