Select2 4.0.0 nilai awal dengan Ajax


98

Saya memiliki select2 v4.0.0 yang diisi dari array Ajax. Jika saya menetapkan val dari select2, saya dapat melihat melalui debugging javascript bahwa ia telah memilih item yang benar (# 3 dalam kasus saya), namun ini tidak ditampilkan di kotak pilih, itu masih menampilkan placeholder. masukkan deskripsi gambar di sini

Padahal saya seharusnya melihat sesuatu seperti ini: masukkan deskripsi gambar di sini

Di bidang formulir saya:

<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 saya:

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

Bagaimana cara membuat kotak pilih memperlihatkan item yang dipilih daripada tempat penampung? Haruskah saya mengirimkan ini sebagai bagian dari tanggapan AJAX JSON?

Di masa lalu, Select2 memerlukan opsi yang disebut initSelection yang ditentukan setiap kali sumber data khusus digunakan, memungkinkan pemilihan awal untuk komponen yang akan ditentukan. Ini bekerja dengan baik untuk saya di v3.5.


Bagaimana mungkin? Ketika saya mencoba mengikat selectdengan ajaxitu naik kesalahan, opsi itu ajax tidak diizinkan dengan pilih ...
Daggeto

Jawaban:


109

Anda melakukan banyak hal dengan benar, tampaknya satu-satunya masalah yang Anda hadapi adalah Anda tidak memicu changemetode setelah Anda menyetel nilai baru. Tanpa changeacara, Select2 tidak bisa mengetahui bahwa nilai yang mendasari telah berubah sehingga hanya akan menampilkan tempat penampung. Mengubah bagian terakhir Anda menjadi

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

Harus memperbaiki masalah Anda, dan Anda akan melihat pembaruan UI segera.


Ini adalah asumsi bahwa Anda memiliki <option>sudah yang memiliki valuedari initial_creditor_id. Jika Anda tidak memilih2, dan browser, tidak akan benar-benar dapat mengubah nilainya, karena tidak ada opsi untuk beralih, dan Select2 tidak akan mendeteksi nilai baru. Saya perhatikan bahwa Anda <select>hanya berisi satu opsi, satu untuk placeholder, yang berarti Anda perlu membuat yang baru <option>secara manual.

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

Dan kemudian tambahkan ke tempat <select>Anda menginisialisasi Select2. Anda mungkin perlu mendapatkan teks dari sumber eksternal, yang biasanya initSelectiondigunakan, yang masih dapat dilakukan dengan Select2 4.0.0. Seperti pemilihan standar, ini berarti Anda harus membuat permintaan AJAX untuk mengambil nilai dan kemudian mengatur <option>teks dengan cepat untuk menyesuaikan.

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

Meskipun ini mungkin terlihat seperti banyak kode, ini persis seperti yang Anda lakukan untuk kotak pilih non-Select2 untuk memastikan bahwa semua perubahan telah dibuat.


14
Tahu bagaimana cara memilih beberapa opsi untuk kotak pilih multi?
pengguna396404

6
@ user396404 konsep yang sama harus diterapkan, cukup teruskan daftar id val()sebagai ganti satu id. Atau cukup tambahkan beberapa <option selected>dan itu harus ditangani secara otomatis.
Kevin Brown

5
Saya menyadari jawaban ini sudah lebih dari satu tahun, tetapi dokumentasi untuk Select2 untuk pertanyaan FAQ: "Bagaimana cara mengatur opsi yang awalnya dipilih saat menggunakan AJAX?" masih menunjukkan ini. Saya telah memasang JSFiddle sebagai contoh yang berfungsi untuk v4.0.3 jsfiddle.net/57co6c95
Clint

2
Ada masalah. Bagaimana jika saya ingin meminta lebih dari sekedar id dan teks? Saya sudah mencoba tetapi opsi data hanya mendapatkan data untuk templateResult dan mengabaikannya untuk templateSelection. Ada ide?
ClearBoth

2
Juga, saya mencoba solusi ini, tetapi sayangnya setelah memanggil $select.trigger('change');opsi tersebut masih dengan teks Memuat ... , meskipun data.textmemiliki teks yang saya inginkan. Mungkin ini tidak lagi didukung di 4.0.6 .
Alisson

29

Apa yang saya lakukan lebih bersih dan perlu membuat dua array:

  • satu berisi daftar Objek dengan id dan teks (dalam kasus saya id dan namanya, tergantung dari templateResult Anda) (itu yang Anda dapatkan dari kueri ajax)
  • yang kedua hanya sebuah array id (nilai pilihan)

Saya menginisialisasi select2 menggunakan array pertama sebagai data, dan yang kedua sebagai val.

Contoh fungsi dengan parameter a dict dari 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');
}

Anda dapat memasukkan nilai inisial menggunakan panggilan ajax, dan menggunakan jquery promise untuk melakukan inisialisasi select2.


3
Ini jelas merupakan cara yang lebih baik untuk melakukannya. Memanipulasi DOM dengan menambahkan <option>tampaknya bukan cara paling logis untuk melakukannya. Ini adalah bagaimana saya melakukannya dalam 4.0
jiaweizhang

2
@ firebird631, solusi Anda brilian, berhasil dan terima kasih banyak!
userlond

ini adalah solusi terbersih yang pernah saya lihat sejauh ini
Jimmy Ilenloa

Saya akan mencatat bahwa secara internal dataopsi hanya menghasilkan <option>tag dan menambahkannya ke pilihan. Jawaban ini tidak mencakup bagaimana Anda menangani kasus di mana Anda perlu pergi ke API untuk mendapatkan lebih banyak informasi, tapi saya rasa itu kasus yang kurang umum.
Kevin Brown

Halo dengan ajax saya tidak bisa melakukannya. Ketika saya mengirim list dengan dua objek tidak ada masalah, ia mencoba memasukkan dua objek itu tetapi hanya satu yang disisipkan. dan sudah dipilih secara otomatis. Saya tidak pernah melihat dua pilihan, bahkan saya mengirim dua item.
Sahin Yanlık

7

Ini bekerja untuk saya ...

Jangan gunakan jQuery, hanya HTML: Buat nilai opsi yang akan Anda tampilkan seperti yang dipilih . Jika ID ada di data select2 maka akan dipilih secara otomatis.

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

Select2.org - Nilai Pre Selected Default


6

Masalah dipaksa trigger('change')membuat saya gila, karena saya memiliki kode khusus di changepemicu, yang seharusnya hanya terpicu ketika pengguna mengubah opsi di tarik-turun. IMO, perubahan tidak boleh dipicu saat menyetel nilai init di awal.

Saya menggali lebih dalam dan menemukan yang berikut: https://github.com/select2/select2/issues/3620

Contoh:

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


4

Satu skenario yang belum pernah saya lihat benar-benar dijawab oleh orang-orang, adalah bagaimana melakukan pemilihan awal ketika opsi bersumber dari AJAX, dan Anda dapat memilih beberapa. Karena ini adalah halaman masuk untuk pemilihan awal AJAX, saya akan menambahkan solusi saya di sini.

$('#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

Jika Anda menggunakan templateSelection dan ajax, beberapa jawaban lain ini mungkin tidak berfungsi. Tampaknya membuat optionelemen baru dan menyetel valuedan texttidak akan memenuhi metode template saat objek data Anda menggunakan nilai selain id dan teks.

Inilah yang berhasil untuk saya:

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

Lihat jsFiddle di sini: https://jsfiddle.net/shanabus/f8h1xnv4

Dalam kasus saya, saya harus processResultsmasuk karena data saya tidak berisi bidang iddan wajib text. Jika Anda perlu melakukan ini, Anda juga perlu menjalankan pemilihan awal melalui fungsi yang sama. Seperti:

$(".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;
}

AKHIRNYA!!!!! Wow, itu sangat membuat frustrasi !! Saya telah menggunakan "nama" daripada "teks" dan itu membunuh saya. Saya beralih ke tombol "teks" default dan sekarang berfungsi dengan sempurna. Terima kasih!
HTMLGuy

1

setelah menghabiskan beberapa jam mencari solusi, saya memutuskan untuk membuatnya sendiri. Dia itu:

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

Dan Anda dapat menginisialisasi pemilihan menggunakan fungsi ini:

$('.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();
            }
        });

Dan tentu saja, inilah html-nya:

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

Ide bagus untuk prosedur inisialisasi generik.
Carlos Mora

1

Untuk solusi sederhana dan semantik, saya lebih suka menentukan nilai awal dalam HTML, contoh:

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

Jadi ketika saya memanggil $('select').select2({ ajax: {...}});nilai awal adalah initial-valuedan teks opsinya adalah Initial text.

Versi Select2 saya saat ini adalah 4.0.3 , tapi menurut saya ini sangat cocok dengan versi lain.


Saya rasa Anda tidak hanya menyimpan nilai pilihan, tetapi juga teks ke database Anda, sehingga Anda dapat mengambilnya kembali seperti itu ... heesh!
ITDesigns.eu

@ ITDesigns.eu, saya rasa tidak, nilai sento ke database adalah initial-valuedan teks Initial textbertindak sebagai placeholder, tidak dikirim ke database. Ini berfungsi di aplikasi saya.
Marcio Mazzucato

mengapa saya membutuhkan placeholder alih-alih teks asli dalam opsi sebenarnya ?!
ITDesigns.eu

@ ITDesigns.eu, Select2 menangkap info ini dan memasang dirinya sendiri
Marcio Mazzucato

1

https://github.com/select2/select2/issues/4272 hanya ini yang memecahkan masalah saya. meskipun Anda menetapkan nilai default berdasarkan opsi, Anda harus memformat objek, yang memiliki atribut teks dan inilah yang ingin Anda tampilkan dalam opsi Anda. Jadi, fungsi format Anda harus digunakan ||untuk memilih atribut yang tidak kosong.


0

Saya menambahkan jawaban ini terutama karena saya tidak bisa berkomentar di atas! Saya menemukan itu adalah komentar dari @Nicki dan jsfiddle-nya, https://jsfiddle.net/57co6c95/ , yang akhirnya membuat ini bekerja untuk saya.

Antara lain memberikan contoh format untuk json yang dibutuhkan. Satu-satunya perubahan yang harus saya lakukan adalah bahwa hasil awal saya dikembalikan dalam format yang sama dengan panggilan ajax lainnya jadi saya harus menggunakan

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

daripada

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

0

Buat kombo ajax sederhana dengan nilai awal seleted untuk 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>  

library .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
        });
    }
}
};

dan sisi server 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

Hai hampir keluar dari ini dan kembali untuk memilih 3.5.1. Tapi akhirnya saya mendapat jawabannya!

$('#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');

Pastikan bahwa opsi baru adalah salah satu opsi select2. Saya mendapatkan ini dengan json.


Hai - apa itu '#status'? haruskah itu menjadi '#test'?
pengguna2808054
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.