Select2 4.0.0 початкове значення за допомогою Ajax


97

У мене є select2 v4.0.0, який заповнюється з масиву Ajax. Якщо я встановив val для 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нього, виникає помилка, цей параметр ajax не дозволяється з select ...
Daggeto 02

Привіт, будь ласка , зверніть увагу на 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>і це повинно оброблятися автоматично.
Kevin Brown

5
Я усвідомлюю, що цій відповіді вже більше року, але документація до Select2 для запитання про поширені запитання: "Як я можу встановити початково вибрані параметри під час використання AJAX?" все ще вказує на це. Я додав JSFiddle як робочий приклад для v4.0.3 jsfiddle.net/57co6c95
Клінт,

2
Є проблема. Що робити, якщо я хочу запитати більше, ніж просто ідентифікатор та текст? Я спробував, але варіант даних лише отримує дані для templateResult і ігнорує їх для templateSelection. Будь-яка ідея?
ClearBoth

2
Крім того, я спробував це рішення, але, на жаль, після виклику $select.trigger('change');опція все ще з текстом " Завантаження ..." , хоча data.textу мене був саме той текст, який я хотів. Можливо, це більше не підтримується в 4.0.6 .
Аліссон,

28

Те, що я зробив, є більш чистим і потребує створення двох масивів:

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

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

Приклад функції з параметрами dict of 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

2
@ firebird631, ваше рішення є чудовим, воно працює, і дуже велике спасибі!
userlond

це найчистіше рішення, яке я бачив досі
Джиммі Іленлоа,

Зазначу, що внутрішньо dataопція просто генерує <option>теги та додає їх до вибраного. Ця відповідь не охоплює, як ви обробляєте випадки, коли вам потрібно звернутися до API, щоб отримати більше інформації, але я думаю, це менш типовий випадок.
Kevin Brown

Привіт з 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тригері я мав власний код , який повинен спрацьовувати лише тоді, коли користувач змінює параметр у спадному меню. IMO, зміна не повинна ініціюватися при встановленні значення початку на початку.

Я глибоко копав і знайшов таке: 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 , але я думаю, що вона чудово сумісна з іншими версіями.


Думаю, ви зберігаєте не лише вибране значення, а й текст у своїй базі даних, тож ви можете отримати його таким чином ... sheesh!
ITDesigns.eu

@ ITDesigns.eu, я не думаю, що значення sento до бази даних є, initial-valueа текст Initial textвиступає як заповнювач, він не надсилається до бази даних. Це працює в моєму додатку.
Marcio Mazzucato

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

@ ITDesigns.eu, Select2 ловить цю інформацію і монтується сам
Marcio Mazzucato

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.