Select2 раскрывающийся список, но разрешить новые значения пользователем?

125

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

Я вижу, что select2 поддерживает это, если вы используете его в tagsрежиме, но есть ли способ сделать это без использования тегов?

Джон Джон
источник
1
Select2 никогда не работал у меня, по крайней мере createSearchChoice никогда не работал у меня в 4.0.3, и я не хотел, чтобы мои пользователи дожидались завершения ajax, чтобы вернуть то же ключевое слово, поэтому мне пришлось развернуть свою собственную библиотеку, я только поделитесь им, потому что я думаю, что это может помочь другим, которые все еще сбиты с толку, как и я, пожалуйста, не голосуйте, если вы не согласны с моим ответом: github.com/razzbee/tagcomplete
razzbee

Ответы:

100

Для версии 4+ проверить этот ответ ниже, Кевин Браун

В Select2 3.5.2 и ниже вы можете использовать что-то вроде:

$(selector).select2({
  minimumInputLength:1,
  "ajax": {
    data:function (term, page) {
      return { term:term, page:page };
    },
    dataType:"json",
    quietMillis:100,
    results: function (data, page) {
      return {results: data.results};
    },
    "url": url
  },
  id: function(object) {
    return object.text;
  },
  //Allow manually entered text in drop down.
  createSearchChoice:function(term, data) {
    if ( $(data).filter( function() {
      return this.text.localeCompare(term)===0;
    }).length===0) {
      return {id:term, text:term};
    }
  },
});

(взято из ответа в списке рассылки select2, но сейчас не могу найти ссылку)

fmpwizard
источник
4
Извините за поздний ответ, но большое спасибо за ваше решение! Другой постер, кстати, разместил ссылку на вашу суть, что делает вас вдвойне крутым! :)
johnjohn
rrauenza потрясающий, именно то, что я искал
Matthias S
4
Добавление selectOnBlur: trueсделает работу смотрите: stackoverflow.com/questions/25616520/...
Реза Фаттахи
1
Просто предупреждение для будущих читателей, вы, вероятно, захотите использовать tags: []вместе с ним createSearchChoice.
Кевин Браун
5
Связанная выше скрипка кажется сломанной.
Wolfr
175

Отличный ответ предоставляется @fmpwizard работ по выбор2 3.5.2 и ниже, но это не будет работать в 4.0.0 .

С самого начала (но, возможно, не так рано), Select2 поддерживал «тегирование»: когда пользователи могут добавлять свои собственные значения, если вы им разрешите. Это можно включить с помощью этой tagsопции, и вы можете поиграть с примером в документации .

$("select").select2({
  tags: true
});

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

$("select").select2({
  tags: true,
  createTag: function (params) {
    return {
      id: params.term,
      text: params.term,
      newOption: true
    }
  }
});

Помимо того, что он служит легко заметным флажком на объекте, проходящем через select2:select событие, дополнительное свойство также позволяет вам визуализировать параметр несколько иначе в результате. Итак, если вы хотите визуально обозначить тот факт, что это новая опция, поставив рядом с ней « (новый) », вы можете сделать что-то вроде этого.

$("select").select2({
  tags: true,
  createTag: function (params) {
    return {
      id: params.term,
      text: params.term,
      newOption: true
    }
  },
  templateResult: function (data) {
    var $result = $("<span></span>");

    $result.text(data.text);

    if (data.newOption) {
      $result.append(" <em>(new)</em>");
    }

    return $result;
  }
});
Кевин Браун
источник
Это было очень полезно @ Markus1980Wien
abiieez
Думаю, я использовал этот фрагмент несколько раз.
Саху В Кумар
Если не работает двойная проверка, вам нужно добавить эту опцию в select2, а не добавлять в параметры ajax. для select2 ajax
Zohaib
2
Его работа в версии select2 (4.0.6) выполняется следующим образом: $ ("select"). Select2 ({tags: true, createTag: function (params) {return {id: params.term, text: params.term, newOption : true}}, templateResult: function (data) {var result = data.text; if (data.newOption) {result = result + '(new)';} return result;}}); спасибо @Kevin Brown
M. Salah
Это должен быть самый главный ответ. Я долго искал это, и этот вариант отвечает на все вопросы, которые я видел по этой теме.
Джастин
14

Просто ради сохранения кода я публикую код @rrauenza Fiddle из его комментария .

HTML

<input type='hidden' id='tags' style='width:300px'/>

JQuery

$("#tags").select2({
    createSearchChoice:function(term, data) { 
        if ($(data).filter(function() { 
            return this.text.localeCompare(term)===0; 
        }).length===0) 
        {return {id:term, text:term};} 
    },
    multiple: false,
    data: [{id: 0, text: 'story'},{id: 1, text: 'bug'},{id: 2, text: 'task'}]
});
Мишель Эйрес
источник
2
Я перешел к скрипке, но, похоже, у меня она не работает в Chrome. Можешь подтвердить?
IcedDante
@IcedDante код работает. суть скрипки - просто показать, как это должно быть сделано (выделение скрыто в скрипке)
Мишель Эйрес,
4
Когда я перехожу к скрипке, я нигде не вижу раскрывающегося списка select2. Было бы неплохо иметь пример, который на самом деле ... что-то делает?
IcedDante
Как я могу установить данные из внешнего источника? Я имею в виду, что, если я хочу загрузить города выбранной страны, а сама выбранная страна является выпадающим списком?
Али Байг
12

Поскольку многие из этих ответов не работают в 4.0+, если вы используете ajax, вы можете попросить сервер добавить новое значение в качестве опции. Итак, это будет работать так:

  1. Пользователь ищет значение (что делает запрос ajax к серверу)
  2. Если значение оказалось большим, верните опцию. Если не просто сервер добавляет эту опцию, например:[{"text":" my NEW option)","id":"0"}]
  3. Когда форма отправлена, просто проверьте, есть ли эта опция в базе данных, и если нет, создайте ее перед сохранением.
Эрик
источник
6

Думаю, теперь есть лучшее решение

просто установите теги в значение true в параметрах выбора?

tags: true

с https://select2.org/tagging

Стивен Моффат
источник
4

Улучшение ответа @fmpwizard:

//Allow manually entered text in drop down.
createSearchChoice:function(term, data) {
  if ( $(data).filter( function() {
    return term.localeCompare(this.text)===0; //even if the this.text is undefined it works
  }).length===0) {
    return {id:term, text:term};
  }
},

//solution to this error: Uncaught TypeError: Cannot read property 'localeCompare' of undefined
Викаш Сингх
источник
Я использовал это с небольшими изменениями, я поставлю свой ответ через секунду, но спасибо.
Сэм
1
var text = 'New York Mills';
var term = 'new york mills';
return text.localeCompare(term)===0;

В большинстве случаев нам нужно сравнивать значения с нечувствительным регистром. И этот код вернет false, что приведет к созданию повторяющихся записей в базе данных. Более того, String.prototype.localeCompare () не поддерживается браузером Safary, и этот код не будет работать в этом браузере;

return this.text.localeCompare(term)===0;

лучше заменить на

return this.text.toLowerCase() === term.toLowerCase();
outdead
источник
1

Спасибо за помощь, ребята, я использовал приведенный ниже код в Codeigniter II. Я использую версию: 3.5.2 select2.

var results = [];
var location_url = <?php echo json_encode(site_url('job/location')); ?>;
$('.location_select').select2({
    ajax: {
        url: location_url,
        dataType: 'json',
        quietMillis: 100,
        data: function (term) {
            return {
                term: term
            };
        },
        results: function (data) {
            results = [];
            $.each(data, function(index, item){
                results.push({
                    id: item.location_id,
                    text: item.location_name
                });
            });
            return {
                results: results
            };
        }
    },
    //Allow manually entered text in drop down.
    createSearchChoice:function(term, results) {
        if ($(results).filter( function() {
            return term.localeCompare(this.text)===0; 
        }).length===0) {
            return {id:term, text:term + ' [New]'};
        }
    },
});
Сэм
источник