Wybierz wartość początkową 4.0.0 z Ajax


98

Mam select2 v4.0.0 wypełniane z tablicy Ajax. Jeśli ustawię wartość select2, widzę przez debugowanie javascript, że wybrał prawidłowy element (nr 3 w moim przypadku), jednak nie jest to pokazane w polu wyboru, nadal pokazuje symbol zastępczy. wprowadź opis obrazu tutaj

Podczas gdy powinienem zobaczyć coś takiego: wprowadź opis obrazu tutaj

W moich polach formularza:

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

Mój 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);

Jak sprawić, by pole wyboru wyświetlało wybrany element zamiast symbolu zastępczego? Czy powinienem to wysyłać jako część odpowiedzi AJAX JSON?

W przeszłości Select2 wymagało opcji o nazwie initSelection, która była definiowana za każdym razem, gdy używane było niestandardowe źródło danych, umożliwiając początkową selekcję komponentu do określenia. To działało dobrze dla mnie w wersji 3.5.


Jak to możliwe? Kiedy próbuję się selectz ajaxnim
połączyć, pojawia

Odpowiedzi:


109

Większość rzeczy wykonujesz poprawnie, wygląda na to, że jedynym problemem, jaki napotykasz, jest to, że nie uruchamiasz changemetody po ustawieniu nowej wartości. Bez changezdarzenia Select2 nie może wiedzieć, że podstawowa wartość uległa zmianie, więc wyświetli tylko symbol zastępczy. Zmiana ostatniej części na

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

Powinno rozwiązać problem i od razu powinna pojawić się aktualizacja interfejsu użytkownika.


Zakłada się, że masz <option>już plik valuez initial_creditor_id. Jeśli nie wybierzesz Select2, a przeglądarka w rzeczywistości nie będzie w stanie zmienić wartości, ponieważ nie ma opcji przełączenia, a Select2 nie wykryje nowej wartości. Zauważyłem, że masz <select>tylko jedną opcję, tę dla symbolu zastępczego, co oznacza, że ​​będziesz musiał <option>ręcznie utworzyć nowy .

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

A następnie dołącz go do tego <select>, na którym zainicjowałeś Select2. Być może będziesz musiał pobrać tekst z zewnętrznego źródła, które było tam initSelectionużywane, co jest nadal możliwe z Select2 4.0.0. Podobnie jak w przypadku standardowego wyboru, oznacza to, że będziesz musiał wykonać żądanie AJAX, aby pobrać wartość, a następnie ustawić <option>tekst w locie, aby dostosować.

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

Chociaż może to wyglądać na dużo kodu, dokładnie tak zrobiłbyś to dla pól wyboru innych niż Select2, aby upewnić się, że wszystkie zmiany zostały wprowadzone.


14
Masz pomysł, jak wstępnie wybrać wiele opcji dla pól wielokrotnego wyboru?
user396404

6
@ user396404 powinny obowiązywać te same koncepcje, po prostu przekaż listę identyfikatorów val()zamiast pojedynczego identyfikatora. Lub po prostu dodaj wiele <option selected>i powinno to być obsługiwane automatycznie.
Kevin Brown,

5
Zdaję sobie sprawę, że ta odpowiedź ma ponad rok, ale dokumentacja Select2 dotycząca pytania FAQ: „Jak ustawić początkowo wybrane opcje podczas korzystania z AJAX?” wciąż na to wskazuje. Załączam JSFiddle jako działający przykład dla v4.0.3 jsfiddle.net/57co6c95
Clint

2
Tam jest problem. A jeśli chcę poprosić o coś więcej niż tylko identyfikator i SMS? Próbowałem, ale opcja danych pobiera tylko dane dla templateResult i zignoruj ​​ją dla templateSelection. Dowolny pomysł?
ClearBoth

2
Próbowałem też tego rozwiązania, ale niestety po wywołaniu $select.trigger('change');opcja nadal ma tekst Loading ... mimo że data.textmiał dokładnie taki tekst jaki chciałem. Być może nie jest to już obsługiwane w wersji 4.0.6 .
Alisson,

29

To, co zrobiłem, jest bardziej przejrzyste i wymaga utworzenia dwóch tablic:

  • jeden zawiera listę Object z id i tekstem (w moim przypadku jego id i nazwę, w zależności od twojego templateResult) (to co otrzymujesz z zapytania Ajax)
  • druga to tylko tablica identyfikatorów (wartość wyboru)

Inicjalizuję select2, używając pierwszej tablicy jako danych, a drugiej jako wartości val.

Przykładowa funkcja, której parametrami są słowa id: nazwa.

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

Możesz podać wartość inicjałów za pomocą wywołań ajax i użyć obietnic jquery do wykonania inicjalizacji select2.


3
To zdecydowanie lepszy sposób na zrobienie tego. Manipulowanie DOM poprzez dodawanie <option>nie wydaje się być najbardziej logicznym sposobem na zrobienie tego. Tak to robię w 4.0
jiaweizhang

2
@ firebird631, Twoje rozwiązanie jest genialne, działa i bardzo wielkie dzięki!
userlond

to najczystsze rozwiązanie, jakie do tej pory widziałem
Jimmy Ilenloa,

Zaznaczę, że wewnętrznie dataopcja polega tylko na wygenerowaniu <option>tagów i dodaniu ich do selekcji. Ta odpowiedź nie obejmuje tego, jak radzisz sobie z przypadkami, w których musisz udać się do API, aby uzyskać więcej informacji, ale wydaje mi się, że jest to mniej typowy przypadek.
Kevin Brown

Witam z Ajax Nie jestem w stanie tego zrobić. Kiedy wysyłam listę z dwoma obiektami, nie ma problemu, próbuje wstawić te dwa obiekty, ale tylko jeden wstawiony. i już wybrane automatycznie. Nigdy nie widziałem dwóch opcji, nawet wysłałem dwie rzeczy.
Sahin Yanlık

7

To działa na mnie ...

Nie używaj jQuery, tylko HTML: utwórz wartość opcji , która zostanie wyświetlona jako wybrana . Jeśli ID znajduje się w danych select2 , zostanie wybrane automatycznie.

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

Select2.org - domyślne wstępnie wybrane wartości


6

Kwestia bycia zmuszonym do trigger('change')doprowadzania mnie do szału, ponieważ miałem niestandardowy kod w changewyzwalaczu, który powinien się uruchamiać tylko wtedy, gdy użytkownik zmieni opcję w menu. IMO, zmiana nie powinna być wyzwalana podczas ustawiania wartości inicjalizacyjnej na początku.

Kopałem głęboko i znalazłem: https://github.com/select2/select2/issues/3620

Przykład:

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


4

Jednym ze scenariuszy, na który nie widziałem, aby ludzie naprawdę odpowiadali, jest to, jak dokonać preselekcji, gdy opcje pochodzą z AJAX i możesz wybrać wiele. Ponieważ jest to strona do przejścia do preselekcji AJAX, dodam tutaj moje rozwiązanie.

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

Jeśli używasz templateSelection i Ajax, niektóre z tych odpowiedzi mogą nie działać. Wygląda na to, że utworzenie nowego optionelementu i ustawienie valuei textnie spełni warunków szablonu, gdy obiekty danych używają innych wartości niż id i tekst.

Oto, co zadziałało dla mnie:

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

Sprawdź jsFiddle tutaj: https://jsfiddle.net/shanabus/f8h1xnv4

W moim przypadku musiałem to zrobić, processResultsponieważ moje dane nie zawierały wymaganych pól idi text. Jeśli musisz to zrobić, musisz również uruchomić początkowy wybór za pomocą tej samej funkcji. Tak jak to:

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

WRESZCIE!!!!! Wow, to nie mogło być bardziej frustrujące !! Używałem „imienia” zamiast „tekstu” i to mnie zabijało. Przełączyłem się na domyślny klawisz „tekstowy” i teraz działa idealnie. Dziękuję Ci!
HTMLGuy

1

po kilku godzinach szukania rozwiązania postanowiłem stworzyć własne. On to jest:

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

I możesz zainicjować selekcje za pomocą tej funkcji:

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

I oczywiście tutaj jest html:

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

Świetny pomysł na ogólną procedurę inicjalizacji.
Carlos Mora

1

Dla prostego i semantycznego rozwiązania wolę zdefiniować wartość początkową w HTML, na przykład:

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

Więc kiedy $('select').select2({ ajax: {...}});wywołuję wartość początkową to, initial-valuea tekst opcji to Initial text.

Moja obecna wersja Select2 to 4.0.3 , ale myślę, że ma świetną kompatybilność z innymi wersjami.


Wydaje mi się, że zapisujesz nie tylko wybraną wartość, ale także tekst w swojej bazie danych, więc możesz go odzyskać w ten sposób ... sheesh!
ITDesigns.eu

@ ITDesigns.eu, nie sądzę, wartość wysyłana do bazy danych to, initial-valuea tekst Initial textpełni rolę symbolu zastępczego, nie jest wysyłany do bazy danych. Działa w mojej aplikacji.
Marcio Mazzucato,

dlaczego miałbym potrzebować symbolu zastępczego zamiast prawdziwego tekstu w rzeczywistej opcji ?!
ITDesigns.eu

@ ITDesigns.eu, Select2 przechwytuje te informacje i zamontuje się
Marcio Mazzucato

1

https://github.com/select2/select2/issues/4272 tylko to rozwiązało mój problem. nawet jeśli ustawisz wartość domyślną za pomocą opcji, musisz sformatować obiekt, który ma atrybut tekstowy i to właśnie chcesz pokazać w swojej opcji. tak więc Twoja funkcja formatu musi użyć ||do wybrania atrybutu, który nie jest pusty.


0

Dodaję tę odpowiedź głównie dlatego, że nie mogę komentować powyżej! Okazało się, że to komentarz @Nicki i jej jsfiddle, https://jsfiddle.net/57co6c95/ , ostatecznie sprawił, że to zadziałało .

Między innymi podał przykłady formatu potrzebnego pliku json. Jedyną zmianą, jaką musiałem wprowadzić, było to, że moje początkowe wyniki zostały zwrócone w tym samym formacie, co inne wywołanie Ajax, więc musiałem użyć

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

zamiast

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

0

Utwórz proste combo ajax z początkową wybraną wartością dla 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>  

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

i po stronie serwera 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

Cześć, prawie kończyłem pracę i wróć do wybrania 3.5.1. Ale w końcu dostałem odpowiedź!

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

Upewnij się tylko, że nowa opcja jest jedną z opcji select2. Dostaję to przez json.


Cześć - co to jest „#status”? czy to powinien być „#test”?
user2808054
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.