Select2 4.0.0 начальное значение с Ajax


98

У меня select2 v4.0.0 заполняется из массива Ajax. Если я устанавливаю значение select2, я могу видеть с помощью отладки javascript, что он выбрал правильный элемент (# 3 в моем случае), однако это не отображается в поле выбора, он все еще показывает заполнитель. введите описание изображения здесь

Тогда как я должен был видеть что-то вроде этого: введите описание изображения здесь

В моих полях формы:

<input name="creditor_id" type="hidden" value="3">
<div class="form-group minimal form-gap-after">
    <span class="col-xs-3 control-label minimal">
        <label for="Creditor:">Creditor:</label>
    </span>
    <div class="col-xs-9">
        <div class="input-group col-xs-8 pull-left select2-bootstrap-prepend">
            <select class="creditor_select2 input-xlarge form-control minimal select2 col-xs-8">
                <option></option>
            </select>
        </div>
    </div>
</div>

Мой javascript:

var initial_creditor_id = "3";
$(".creditor_select2").select2({
    ajax: {
       url: "/admin/api/transactions/creditorlist",
       dataType: 'json',
       delay: 250,
       data: function (params) {
           return {
                q: params.term,
                c_id: initial_creditor_id,
                page: params.page
           };
       },
       processResults: function (data, page) {
            return {
                results: data
            };
       },
       cache: true
   },
   placeholder: "Search for a Creditor",
   width: "element",
   theme: "bootstrap",
   allowClear: true
   }).on("select2:select", function (e) {
      var selected = e.params.data;
      if (typeof selected !== "undefined") {
           $("[name='creditor_id']").val(selected.creditor_id);
           $("#allocationsDiv").hide();
           $("[name='amount_cash']").val("");
           $("[name='amount_cheque']").val("");
           $("[name='amount_direct']").val("");
           $("[name='amount_creditcard']").val("");
        }
    }).on("select2:unselecting", function (e) {
        $("form").each(function () {
            this.reset()
        });
        ("#allocationsDiv").hide();
        $("[name='creditor_id']").val("");
    }).val(initial_creditor_id);

Как сделать так, чтобы в поле выбора отображался выбранный элемент, а не заполнитель? Может быть, я должен отправить это как часть ответа AJAX JSON?

Раньше для Select2 требовалась опция initSelection, которая определялась всякий раз, когда использовался пользовательский источник данных, что позволяло определять первоначальный выбор компонента. У меня это отлично работало в версии 3.5.


Насколько это возможно? Когда я пытаюсь привязать selectс ajaxподнимается ошибку, что опция АЯКС его не допускается выбрать ...
Daggeto

Привет, пожалуйста, взгляните на stackoverflow.com/questions/42833778/…
Vivekraj KR

Ответы:


109

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

.val(initial_creditor_id).trigger('change');

Должна исправить вашу проблему, и вы должны сразу увидеть обновление пользовательского интерфейса.


Предполагается, что у вас <option>уже есть файл valueиз initial_creditor_id. Если вы не выберете Select2, и браузер не сможет фактически изменить значение, так как нет возможности переключиться, и Select2 не обнаружит новое значение. Я заметил, что у вас есть <select>только один вариант, один для заполнителя, что означает, что вам нужно будет создать новый <option>вручную.

var $option = $("<option selected></option>").val(initial_creditor_id).text("Whatever Select2 should display");

А затем добавьте его к тому, на <select>котором вы инициализировали Select2. Возможно, вам потребуется получить текст из внешнего источника, который initSelectionраньше использовался, что все еще возможно с Select2 4.0.0. Как и при стандартном выборе, это означает, что вам нужно будет сделать запрос AJAX для получения значения, а затем <option>на лету установить текст для настройки.

var $select = $('.creditor_select2');

$select.select2(/* ... */); // initialize Select2 and any events

var $option = $('<option selected>Loading...</option>').val(initial_creditor_id);

$select.append($option).trigger('change'); // append the option and update Select2

$.ajax({ // make the request for the selected data object
  type: 'GET',
  url: '/api/for/single/creditor/' + initial_creditor_id,
  dataType: 'json'
}).then(function (data) {
  // Here we should have the data object
  $option.text(data.text).val(data.id); // update the text that is displayed (and maybe even the value)
  $option.removeData(); // remove any caching data that might be associated
  $select.trigger('change'); // notify JavaScript components of possible changes
});

Хотя это может выглядеть как большой объем кода, это именно то, как вы бы сделали это для полей выбора, отличных от Select2, чтобы гарантировать, что все изменения были внесены.


14
Есть идеи, как предварительно выбрать несколько вариантов для множественного выбора?
user396404

6
@ user396404 должны применяться те же концепции, просто передайте список идентификаторов val()вместо одного идентификатора. Или просто добавьте несколько, <option selected>и это должно обрабатываться автоматически.
Кевин Браун,

5
Я понимаю, что этому ответу больше года, но документация для Select2 на вопрос FAQ: «Как я могу установить изначально выбранные параметры при использовании AJAX?» все еще указывает на это. Я прикрепил JSFiddle в качестве рабочего примера для v4.0.3 jsfiddle.net/57co6c95
Клинт

2
Существует проблема. Что, если я хочу запросить больше, чем просто идентификатор и текст? Я пробовал, но опция данных получает данные только для templateResult и игнорирует их для templateSelection. Любая идея?
ClearBoth,

2
Кроме того, я пробовал это решение, но, к сожалению, после вызова $select.trigger('change');опции все еще отображается текст « Загрузка ...» , хотя data.textтекст был именно таким, какой я хотел. Возможно, это больше не поддерживается в 4.0.6 .
Alisson

29

То, что я сделал, более чистое и требует создания двух массивов:

  • один содержит список объектов с идентификатором и текстом (в моем случае его идентификатор и имя, в зависимости от вашего templateResult) (это то, что вы получаете из запроса ajax)
  • второй - только массив идентификаторов (значение выбора)

Я инициализирую select2, используя первый массив как данные, а второй как val.

Пример функции с параметрами id: name.

function initMyList(values) {
    var selected = [];
    var initials = [];

    for (var s in values) {
        initials.push({id: s, name: values[s].name});
        selected.push(s);
    }

    $('#myselect2').select2({
        data: initials,
        ajax: {
            url: "/path/to/value/",
            dataType: 'json',
            delay: 250,
            data: function (params) {
                return {
                    term: params.term,
                    page: params.page || 1,
                };
            },
            processResults: function (data, params) {
                params.page = params.page || 1;

                return {
                    results: data.items,
                    pagination: {
                        more: (params.page * 30) < data.total_count
                    }
                };
            },
            cache: true
        },
        minimumInputLength: 1,
        tokenSeparators: [",", " "],
        placeholder: "Select none, one or many values",
        templateResult: function (item) { return item.name; },
        templateSelection: function (item) { return item.name; },
        matcher: function(term, text) { return text.name.toUpperCase().indexOf(term.toUpperCase()) != -1; },
    });

    $('#myselect2').val(selected).trigger('change');
}

Вы можете передать значение инициалов с помощью вызовов ajax и использовать обещания jquery для инициализации select2.


3
Это определенно лучший способ сделать это. Манипулирование DOM путем добавления <option>кажется не самым логичным способом сделать это. Вот как я это делаю в 4.0
jiaweizhang 02

2
@ firebird631, у вас отличное решение, оно работает и большое спасибо!
userlond

это самое чистое решение, которое я когда-либо видел
Джимми Иленлоа

Замечу, что внутренне dataопция просто генерирует <option>теги и добавляет их в select. В этом ответе не рассматривается, как вы справляетесь со случаями, когда вам нужно обратиться к API для получения дополнительной информации, но я думаю, что это менее типичный случай.
Кевин Браун

Здравствуйте, с помощью ajax я не могу этого сделать. Когда я отправляю список с двумя объектами, проблем нет, он пытается вставить эти два объекта, но вставлен только один. и уже выбран автоматически. Я так и не увидел два варианта, даже отправил два.
Sahin Yanlık

7

У меня работает ...

Не используйте jQuery, только HTML: создайте значение параметра , которое будет отображаться как выбранное . Если идентификатор указан в данных select2, он будет выбран автоматически.

<select id="select2" name="mySelect2">
  <option value="mySelectedValue">
        Hello, I'm here!
  </option>
</select>

Select2.org - предварительно выбранные значения по умолчанию


6

Проблема принуждения trigger('change')сводила меня с ума, поскольку у меня был собственный код в changeтриггере, который должен срабатывать только тогда, когда пользователь изменяет параметр в раскрывающемся списке. ИМО, изменение не должно запускаться при установке значения инициализации в начале.

Я покопался и нашел следующее: https://github.com/select2/select2/issues/3620

Пример:

$dropDown.val(1).trigger('change.select2');


4

Один из сценариев, на который я не видел, чтобы люди действительно отвечали, - это как сделать предварительный выбор, когда параметры получены из AJAX, и вы можете выбрать несколько. Поскольку это страница для предварительного выбора AJAX, я добавлю сюда свое решение.

$('#mySelect').select2({
    ajax: {
        url: endpoint,
        dataType: 'json',
        data: [
            { // Each of these gets processed by fnRenderResults.
                id: usersId,
                text: usersFullName,
                full_name: usersFullName,
                email: usersEmail,
                image_url: usersImageUrl,
                selected: true // Causes the selection to actually get selected.
            }
        ],
        processResults: function(data) {

            return {
                results: data.users,
                pagination: {
                    more: data.next !== null
                }
            };

        }
    },
    templateResult: fnRenderResults,
    templateSelection: fnRenderSelection, // Renders the result with my own style
    selectOnClose: true
}); 

3

Если вы используете templateSelection и ajax, некоторые из этих других ответов могут не работать. Кажется, что создание нового optionэлемента и установка valueи textне удовлетворит метод шаблона, когда ваши объекты данных используют другие значения, кроме id и text.

Вот что у меня сработало:

$("#selectElem").select2({
  ajax: { ... },
  data: [YOUR_DEFAULT_OBJECT],
  templateSelection: yourCustomTemplate
} 

Ознакомьтесь с jsFiddle здесь: https://jsfiddle.net/shanabus/f8h1xnv4

В моем случае, я должен был processResultsв так мои данные не содержат необходимые idи textполе. Если вам нужно это сделать, вам также нужно будет выполнить первоначальный выбор с помощью той же функции. Вот так:

$(".js-select2").select2({
  ajax: {
    url: SOME_URL,
    processResults: processData
  },
  data: processData([YOUR_INIT_OBJECT]).results,
  minimumInputLength: 1,
  templateSelection: myCustomTemplate
});

function processData(data) {
  var mapdata = $.map(data, function (obj) {      
    obj.id = obj.Id;
    obj.text = '[' + obj.Code + '] ' + obj.Description;
    return obj;
  });
  return { results: mapdata }; 
}

function myCustomTemplate(item) {
     return '<strong>' + item.Code + '</strong> - ' + item.Description;
}

НУ НАКОНЕЦ ТО!!!!! Вау, это не могло быть более разочаровывающим !! Я использовал «имя» вместо «текст», и это меня убивало. Я переключился на "текстовую" клавишу по умолчанию, и теперь она работает отлично. Спасибо!
HTMLGuy

1

Потратив несколько часов на поиски решения, я решил создать свое собственное. Он это:

 function CustomInitSelect2(element, options) {
            if (options.url) {
                $.ajax({
                    type: 'GET',
                    url: options.url,
                    dataType: 'json'
                }).then(function (data) {
                    element.select2({
                        data: data
                    });
                    if (options.initialValue) {
                        element.val(options.initialValue).trigger('change');
                    }
                });
            }
        }

И вы можете инициализировать выборку с помощью этой функции:

$('.select2').each(function (index, element) {
            var item = $(element);
            if (item.data('url')) {
                CustomInitSelect2(item, {
                    url: item.data('url'),
                    initialValue: item.data('value')
                });
            }
            else {
                item.select2();
            }
        });

И, конечно же, вот HTML:

<select class="form-control select2" id="test1" data-url="mysite/load" data-value="123"></select>

Отличная идея для общей процедуры инициализации.
Карлос Мора

1

Для простого и семантического решения я предпочитаю определять начальное значение в HTML, например:

<select name="myfield" data-placeholder="Select an option">
    <option value="initial-value" selected>Initial text</option>
</select>

Поэтому, когда я вызываю $('select').select2({ ajax: {...}});начальное значение, initial-valueа его текст опции - Initial text.

Моя текущая версия Select2 - 4.0.3 , но я думаю, что она отлично совместима с другими версиями.


Я предполагаю, что вы сохраняете не только значение выбора, но и текст в своей базе данных, так что вы можете получить его вот так ... блин!
ITDesigns.eu

@ ITDesigns.eu, я так не думаю, значение sento to database равно, initial-valueа текст Initial textдействует как заполнитель, он не отправляется в базу данных. Он работает в моем приложении.
Марсио Маццукато

зачем мне нужен заполнитель вместо реального текста в фактическом варианте ?!
ITDesigns.eu

@ ITDesigns.eu, Select2 улавливает эту информацию и устанавливает себя
Марсио Маццукато

1

https://github.com/select2/select2/issues/4272, только это решило мою проблему. даже если вы установили значение по умолчанию по опции, вы должны отформатировать объект, который имеет текстовый атрибут, и это то, что вы хотите показать в своем варианте. Итак, ваша функция форматирования должна использовать ||для выбора атрибута, который не является пустым.


0

Я добавляю этот ответ в основном потому, что не могу комментировать выше! Я обнаружил, что это был комментарий @Nicki и ее jsfiddle, https://jsfiddle.net/57co6c95/ , который в конечном итоге заставил меня работать.

Среди прочего, он дал примеры необходимого формата json. Единственное изменение, которое мне пришлось сделать, это то, что мои первоначальные результаты были возвращены в том же формате, что и другой вызов ajax, поэтому мне пришлось использовать

$option.text(data[0].text).val(data[0].id);

скорее, чем

$option.text(data.text).val(data.id);

0

Создайте простую комбинацию ajax с начальным выбранным значением для select2 4.0.3

<select name="mycombo" id="mycombo""></select>                   
<script>
document.addEventListener("DOMContentLoaded", function (event) {
    selectMaker.create('table', 'idname', '1', $("#mycombo"), 2, 'type');                                
});
</script>  

библиотека .js

var selectMaker = {
create: function (table, fieldname, initialSelected, input, minimumInputLength = 3, type ='',placeholder = 'Select a element') {
    if (input.data('select2')) {
        input.select2("destroy");
    }
    input.select2({
        placeholder: placeholder,
        width: '100%',
        minimumInputLength: minimumInputLength,
        containerCssClass: type,
        dropdownCssClass: type,
        ajax: {
            url: 'ajaxValues.php?getQuery=true&table=' + table + '&fieldname=' + fieldname + '&type=' + type,
            type: 'post',
            dataType: 'json',
            contentType: "application/json",
            delay: 250,
            data: function (params) {
                return {
                    term: params.term, // search term
                    page: params.page
                };
            },
            processResults: function (data) {
                return {
                    results: $.map(data.items, function (item) {
                        return {
                            text: item.name,
                            id: item.id
                        }
                    })
                };
            }
        }
    });
    if (initialSelected>0) {
        var $option = $('<option selected>Cargando...</option>').val(0);
        input.append($option).trigger('change'); // append the option and update Select2
        $.ajax({// make the request for the selected data object
            type: 'GET',
            url: 'ajaxValues.php?getQuery=true&table=' + table + '&fieldname=' + fieldname + '&type=' + type + '&initialSelected=' + initialSelected,
            dataType: 'json'
        }).then(function (data) {
            // Here we should have the data object
            $option.text(data.items[0].name).val(data.items[0].id); // update the text that is displayed (and maybe even the value)
            $option.removeData(); // remove any caching data that might be associated
            input.trigger('change'); // notify JavaScript components of possible changes
        });
    }
}
};

и на стороне сервера php

<?php
if (isset($_GET['getQuery']) && isset($_GET['table']) && isset($_GET['fieldname'])) {
//parametros carga de petición
parse_str(file_get_contents("php://input"), $data);
$data = (object) $data;
if (isset($data->term)) {
    $term = pSQL($data->term);
}else{
    $term = '';
}
if (isset($_GET['initialSelected'])){
    $id =pSQL($_GET['initialSelected']);
}else{
    $id = '';
}
if ($_GET['table'] == 'mytable' && $_GET['fieldname'] == 'mycolname' && $_GET['type'] == 'mytype') {

    if (empty($id)){
        $where = "and name like '%" . $term . "%'";
    }else{
         $where = "and id= ".$id;
    }

    $rows = yourarrayfunctionfromsql("SELECT id, name 
                    FROM yourtable
                    WHERE 1 " . $where . "
                    ORDER BY name ");
}

$items = array("items" => $rows);
$var = json_encode($items);
echo $var;
?>

-4

Привет, почти бросил это и вернулся, чтобы выбрать 3.5.1. Но наконец я получил ответ!

$('#test').select2({
    placeholder: "Select a Country",
    minimumResultsForSearch: 2,
    ajax: {
        url: '...',
        dataType: 'json',
        cache: false,
        data: function (params) {
                var queryParameters = {
                    q: params.term
                }
                return queryParameters;
        },
        processResults: function (data) {
            return {
                results: data.items
            };
        }
    }
});

var option1 = new Option("new",true, true);

$('#status').append(option1);

$('#status').trigger('change');

Просто убедитесь, что новая опция - одна из опций select2. Я получаю это с помощью json.


Привет, что такое "#status"? должно быть "#test"?
user2808054
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.