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

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

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

Ответ 1

Для версии 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, но не может найти ссылку сейчас)

Ответ 2

отличный ответ, предоставленный @fmpwizard, работает для Select2 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;
  }
});

Ответ 3

Просто ради сохранения кода, я отправляю @rrauenza Fiddle code из его комментарий.

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'}]
});

Ответ 4

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

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

Ответ 5

Устранить ответ @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

Ответ 6

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();

Ответ 7

Я только что наткнулся на это от Кевина Брауна. fooobar.com/questions/619983/...

Все, что вам нужно сделать для v4.0.6 это использовать tags: true параметр.

Ответ 8

Спасибо за помощь, ребята, я использовал код ниже в Codeigniter. Я использую версию: 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]'};
        }
    },
});

Ответ 9

Есть лучшее решение, я думаю, что сейчас

просто установить теги в true на выбранных опциях?

tags: true

с https://select2.org/tagging