Ajax ile 2 4.0.0 başlangıç ​​değerini seçin


98

Ajax dizisinden doldurulan bir select2 v4.0.0'ım var. Select2'nin değerini ayarlarsam, javascript hata ayıklama yoluyla doğru öğeyi seçtiğini görebilirim (benim durumumda # 3), ancak bu seçim kutusunda gösterilmiyor, yine de yer tutucuyu gösteriyor. görüntü açıklamasını buraya girin

Halbuki şöyle bir şey görmeliyim: görüntü açıklamasını buraya girin

Form alanlarımda:

<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'im:

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

Seçim kutusunun yer tutucu yerine seçilen öğeyi göstermesini nasıl sağlayabilirim? Bunu AJAX JSON yanıtının bir parçası olarak göndermeli miyim?

Geçmişte, Select2, özel bir veri kaynağı kullanıldığında tanımlanan ve bileşen için ilk seçimin belirlenmesine izin veren initSelection adlı bir seçeneğe ihtiyaç duyuyordu. Bu benim için v3.5'te iyi çalıştı.


Nasıl mümkün olabilir? İ bağlama çalışıyorum zaman selectile ajaxbu hatayı yükselir, bu seçenek onun ... seçeneğini ile izin verilmez AJAX
Daggeto

Yanıtlar:


109

Çoğu şeyi doğru bir şekilde yapıyorsunuz, vurduğunuz tek sorun change, yeni değeri ayarladıktan sonra yöntemi tetiklememeniz gibi görünüyor . Bir changeolay olmadan , Select2 temel değerin değiştiğini bilemez, bu nedenle yalnızca yer tutucuyu görüntüler. Son bölümünüzü değiştirmek

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

Sorununuzu çözmeli ve hemen UI güncellemesini görmelisiniz.


Bu, bir var varsayarak <option>bir olduğunu zaten valuebir initial_creditor_id. 2 Seçmezseniz ve tarayıcı, geçiş yapma seçeneği olmadığından değeri gerçekten değiştiremez ve Seç2 yeni değeri algılamaz. <select>Tek bir seçeneğinizin yer tutucu için olanı içerdiğini fark ettim , bu da yeniyi <option>manuel olarak oluşturmanız gerektiği anlamına gelir .

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

Ve sonra onu <select>Select2'yi başlattığınız şeye ekleyin . Metni, daha initSelectionönce devreye girdiği yerde harici bir kaynaktan almanız gerekebilir , bu da Select2 4.0.0 ile hala mümkündür. Standart bir seçim gibi, bu, değeri almak için AJAX isteğinde bulunmanız ve ardından <option>metni ayarlamak için anında ayarlamanız gerektiği anlamına gelir.

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

Bu çok fazla kod gibi görünse de, tüm değişikliklerin yapıldığından emin olmak için Select2 dışındaki seçim kutuları için tam olarak bunu yaparsınız .


14
Çoklu seçim kutuları için birden çok seçeneğin nasıl önceden seçileceği hakkında bir fikriniz var mı?
user396404

6
@ user396404 aynı kavramlar geçerli olmalıdır, sadece val()tek bir kimlik yerine bir kimlik listesi iletin . Veya sadece birden fazla ekleyin <option selected>ve bu otomatik olarak ele alınmalıdır.
Kevin Brown

5
Bu cevabın bir yıldan eski olduğunu fark ediyorum, ancak şu SSS sorusu için Select2 dokümantasyonu: "AJAX kullanırken başlangıçta seçilen seçenekleri nasıl ayarlayabilirim?" hala buna işaret ediyor. V4.0.3 için çalışan bir örnek olarak JSFiddle ekledim jsfiddle.net/57co6c95
Clint

2
Bir sorun var. Kimlik ve mesajdan fazlasını talep etmek istersem ne olur? Denedim ama veri seçeneği yalnızca templateResult için veri alıyor ve templateSelection için yoksay Herhangi bir fikir?
ClearBoth

2
Ayrıca, bu çözümü denedim, ancak ne yazık ki aradıktan $select.trigger('change');sonra seçenek hala Yükleniyor ... metniyle birlikte, data.texttam olarak istediğim metin olmasına rağmen . Belki bu artık 4.0.6'da desteklenmiyor .
Alisson

29

Yaptığım şey daha temiz ve iki dizi oluşturmam gerekiyor:

  • biri id ve metin içeren bir Nesne listesi içerir (benim durumumda, templateResult'unuza bağlı olarak kimliği ve adı) (ajax sorgusundan aldığınız şey)
  • ikincisi yalnızca bir kimlik dizisidir (seçim değeri)

İlk diziyi veri olarak ve ikinciyi de değer olarak kullanarak select2'yi başlatıyorum.

Parametre olarak bir id: isim diktesine sahip örnek bir işlev.

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

Başlangıç ​​değerini ajax çağrılarını kullanarak besleyebilir ve select2 ilklendirmesini yapmak için jquery vaatlerini kullanabilirsiniz.


3
Bu kesinlikle bunu yapmanın daha iyi yolu. DOM'u ekleyerek <option>değiştirmek, bunu yapmanın en mantıklı yolu gibi görünmüyor. 4.0'da böyle yapıyorum
jiaweizhang

2
@ firebird631, çözümünüz harika, işe yarıyor ve çok teşekkürler!
userlond

bu şimdiye kadar gördüğüm en temiz çözüm
Jimmy Ilenloa

Dahili olarak dataseçeneğin yalnızca <option>etiketler oluşturup bunları seçime eklemek olduğunu not edeceğim . Bu cevap, daha fazla bilgi almak için bir API'ye gitmeniz gereken durumları nasıl ele aldığınızı kapsamaz, ancak sanırım bu daha az tipik bir durumdur.
Kevin Brown

Merhaba ajax ile yapamıyorum. İki nesne içeren bir liste gönderdiğimde herhangi bir sorun yok, bu iki nesneyi eklemeye çalışıyor ama sadece bir tanesi eklendi. ve zaten otomatik olarak seçildi. İki öğe göndermiş olsam bile iki seçeneği asla göremedim.
Sahin Yanlık

7

Benim için çalışıyor ...

JQuery kullanmayın, yalnızca HTML: Seçili olarak görüntüleyeceğiniz seçenek değerini oluşturun . Kimlik, select2 verilerindeyse , otomatik olarak seçilir.

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

Select2.org - Varsayılan Önceden Seçilmiş değerler


6

Tetikleyicide trigger('change')özel kodum olduğu için beni deli etmeye zorlama sorunu, changeyalnızca kullanıcı açılır menüdeki seçeneği değiştirdiğinde tetiklenmelidir. IMO, başlangıçta bir başlatma değeri ayarlarken değişiklik tetiklenmemelidir.

Derin kazdım ve şunları buldum: https://github.com/select2/select2/issues/3620

Misal:

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


5

İnsanların gerçekten cevapladığını görmediğim bir senaryo, seçenekler AJAX kaynaklı olduğunda nasıl ön seçim yapılacağı ve birden fazla seçim yapabileceğiniz. Bu AJAX ön seçimi için gidilecek sayfa olduğundan, çözümümü buraya ekleyeceğim.

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

Bir templateSelection ve ajax kullanıyorsanız, bu diğer cevaplardan bazıları işe yaramayabilir. Yeni bir yaratma görünüyor optionelemanı ve ayarlama valueve textveri nesneleri kimliği ve metin dışında değerler kullandığınızda şablon yöntemini tatmin olmayacaktır.

İşte benim için işe yarayan şey:

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

JsFiddle'a buradan göz atın: https://jsfiddle.net/shanabus/f8h1xnv4

Benim durumumda, processResultsverilerim gerekli idve textalanları içermediği için girmek zorunda kaldım . Bunu yapmanız gerekiyorsa, ilk seçiminizi de aynı işlevle çalıştırmanız gerekecektir. Şöyle:

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

EN SONUNDA!!!!! Vay canına, bu daha sinir bozucu olamazdı !! "Metin" yerine "isim" kullanıyordum ve beni öldürüyordu. Varsayılan "metin" anahtarına geçtim ve şimdi mükemmel çalışıyor. Teşekkür ederim!
HTMLGuy

1

Bir çözüm arayışıyla birkaç saat geçirdikten sonra, kendi çözümümü oluşturmaya karar verdim. O:

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

Ve bu işlevi kullanarak seçimleri başlatabilirsiniz:

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

Ve tabii ki, işte html:

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

Genel bir başlatma prosedürü için harika bir fikir.
Carlos Mora

1

Basit ve anlamsal bir çözüm için başlangıç ​​değerini HTML'de tanımlamayı tercih ederim, örneğin:

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

Bu yüzden $('select').select2({ ajax: {...}});başlangıç ​​değerini çağırdığımda is initial-valueve onun seçenek metni Initial text.

Şu anki Select2 sürümüm 4.0.3 , ancak diğer sürümlerle mükemmel bir uyumluluğu olduğunu düşünüyorum.


Sanırım sadece seçilmiş bir değeri değil, aynı zamanda veritabanınıza bir metin de kaydediyorsunuz, böylece onu bu şekilde geri alabilirsiniz ... sheesh!
ITDesigns.eu

@ ITDesigns.eu, ben öyle düşünmüyorum, sento'nun veritabanının değeri initial-valueve metin Initial textbir yer tutucu görevi görüyor, veritabanına gönderilmiyor. Uygulamamda çalışıyor.
Marcio Mazzucato

gerçek seçenekte gerçek bir metin yerine neden bir yer tutucuya ihtiyacım olsun ki ?
ITDesigns.eu

@ ITDesigns.eu, Select2 bu bilgiyi yakalar ve kendini monte eder
Marcio Mazzucato

1

https://github.com/select2/select2/issues/4272 sadece bu benim sorunumu çözdü. varsayılan değeri isteğe bağlı olarak ayarlasanız bile, text niteliğine sahip olan nesneyi biçimlendirmeniz gerekir ve bu, seçeneğinizde göstermek istediğiniz şeydir. bu nedenle, biçim işleviniz ||boş olmayan özniteliği seçmek için kullanmalıdır .


0

Bu yanıtı ekliyorum çünkü yukarıda yorum yapamam! @Nicki ve jsfiddle'ın yorumu, https://jsfiddle.net/57co6c95/ , sonunda bunu benim için çalıştırdı.

Diğer şeylerin yanı sıra, ihtiyaç duyulan json formatının örneklerini verdi. Yapmam gereken tek değişiklik, ilk sonuçlarımın diğer ajax çağrısıyla aynı biçimde döndürülmesiydi, bu yüzden kullanmak zorunda kaldım

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

ziyade

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

0

Select2 4.0.3 için ilk seçilen değerle basit ajax kombinasyonu oluşturun.

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

kütüphane .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
        });
    }
}
};

ve php sunucu tarafı

<?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

Merhaba, neredeyse bundan çıkıyordu ve 3.5.1'i seçmek için geri dönüyordu. Ama sonunda cevabı aldım!

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

Yeni seçeneğin seç2 seçeneklerinden biri olduğundan emin olun. Bunu bir json'dan alıyorum.


Merhaba - "#status" nedir? bu '#test' olmalıdır?
user2808054
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.