最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Loading remote data only once with Select2 - Stack Overflow

programmeradmin3浏览0评论

As the title suggests I would like to load remote data once only. I thought about loading a data with independent ajax call and set it "locally" at the control but wonder if there is more "built in" way to do so...

As the title suggests I would like to load remote data once only. I thought about loading a data with independent ajax call and set it "locally" at the control but wonder if there is more "built in" way to do so...

Share Improve this question asked Dec 20, 2013 at 10:30 YaronYaron 2,7194 gold badges21 silver badges35 bronze badges 1
  • I dont think there is any inbuilt option in select2 which gives you that flexibility, the only way of doing it would be to control the ajax call based on whether it has been called earlier or not.this controlling should be within the initselection: of select2 – dreamweiver Commented Dec 20, 2013 at 10:45
Add a comment  | 

4 Answers 4

Reset to default 10

a solution can be found here:

https://github.com/ivaynberg/select2/issues/110

$("#selIUT").select2({
    cacheDataSource: [],
    placeholder: "Please enter the name",
    query: function(query) {
        self = this;
        var key = query.term;
        var cachedData = self.cacheDataSource[key];

        if(cachedData) {
            query.callback({results: cachedData.result});
            return;
        } else {
            $.ajax({
              url: '/ajax/suggest/',
              data: { q : query.term },
              dataType: 'json',
              type: 'GET',
              success: function(data) {
                self.cacheDataSource[key] = data;
                query.callback({results: data.result});
              }
            })
        }
    },
    width: '250px',
    formatResult: formatResult, 
    formatSelection: formatSelection, 
    dropdownCssClass: "bigdrop", 
    escapeMarkup: function (m) { return m; } 
}); 

Edit:

I might have misinterpreted your question. if you wish to load all data once, then use that is Select2, there is no built in functionality to do that.

Your suggestion to do a single query, and then use that stored data in Select2 would be the way to go.

This is for Select2 v4.0.3:

I had this same question and got around it by triggering an AJAX call and using the data returned as the initialized data array.

// I used an onClick event to fire the AJAX, but this can be attached to any event.
// Ensure ajax call is done *ONCE* with the "one" method.
$('#mySelect').one('click', function(e) {
    // Text to let user know data is being loaded for long requests.
    $('#mySelect option:eq(0)').text('Data is being loaded...');
    $.ajax({
        type: 'POST',
        url: '/RetrieveDropdownOptions',
        data: {}, // Any data that is needed to pass to the controller
        dataType: 'json',
        success: function(returnedData) {
            // Clear the notification text of the option.
            $('#mySelect option:eq(0)').text('');
            // Initialize the Select2 with the data returned from the AJAX.
            $('#mySelect').select2({ data: returnedData });
            // Open the Select2.
            $('#mySelect').select2('open');
        }
    });
    // Blur the select to register the text change of the option.
    $(this).blur();
});

This worked well for what I had in mind. Hope this helps people searching with the same question.

To load data once:

Assumptions:

  • You have a REST API endpoint at /services that serves a JSON array of objects

  • The array contains objects which have at least a "name" and "id" attribute. Example:

    [{"id": 0, "name": "Foo"}, {"id": 1, "name": "Bar"}]
    
  • You want to store that array as the global 'services_raw'

First, our function to load the data and create the global 'services_raw' (AKA 'window.services_raw'):

  fetchFromAPI = function() {
        console.log("fetchFromAPI called");
        var jqxhr = $.ajax(
            {
                dataType:'json',
                type: 'GET',
                url: "/services",
                success: function(data, textStatus, jqXHR) {
                    services_raw = data;
                    console.log("rosetta.fn.fetchServicesFromAPI SUCCESS");
                    rosetta.fn.refreshServicesSelect();
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    console.log("Error inside rosetta.fn.fetchServicesFromAPI", errorThrown, textStatus, jqXHR);
                    setTimeout(rosetta.fn.fetchServicesFromAPI(), 3000);  // retry in 3 seconds
                }
            }
        )
            .done(function () {
                console.log("success");
                console.log(jqxhr);
            })
            .fail(function () {
                console.log("error");
            })
            .always(function () {
                console.log("complete");
            });

        // Perform other work here ...

        // Set another completion function for the request above
        jqxhr.always(function () {
            console.log("second complete");
        });
    };

Second, our Select2 instantiation code which transforms our data into a format that Select2 can work with:

refreshServicesSelect = function () {
    // ref: http://jsfiddle.net/RVnfn/2/
    // ref2: http://jsfiddle.net/RVnfn/101/    # mine
    // ref3: http://jsfiddle.net/RVnfn/102/    # also mine

    console.log('refreshServicesSelect called');
    $("#add-service-select-service").select2({
        // allowClear: true
        data: function() {
            var arr = [];  // container for the results we're returning to Select2 for display

            for (var idx in services_raw) {
                var item = services_raw[idx];
                arr.push({
                    id: item.id,
                    text: item.name,
                    _raw: item  // for convenience
                });
            }
            return {results: arr};
        }
    });
};

Here's what the Select2 element in HTML should look like before your call the above functions:

<input id="add-service-select-service" type="hidden" style="width:100%">

To use all of this, call (in JS):

window.fetchFromAPI();
window.refreshServicesSelect();

Lastly, here's a JSFiddle where you can play with a similar thing: http://jsfiddle.net/RVnfn/102/

Basically, in my example above, we're just using ajax to populate the equivalent of window.pills in the Fiddle.

Hope this helps :)

Please reply if you know how to do this via the Select2 .ajax function, as that would be a bit shorter.

In my condition, it is working perfectly with the given code

$('#itemid').select2({
    cacheDataSource: [],
    closeOnSelect: true,
    minimumInputLength: 3,
    placeholder: "Search Barcode / Name",
    query: function(query) {
        // console.log(query);
        self = this;
        var key = query.term;
        var cachedData = self.cacheDataSource[key];
        if(cachedData) {
            query.callback({results: cachedData});
            return;
        } else {
            $.ajax({
                url: "./includes/getItemSelect2.php",
                data: { value : query.term },
                dataType: 'json',
                type: 'POST',
                success: function(data) {
                    self.cacheDataSource[key] = data;
                    query.callback({results: data});
                }
            });
        }
    },
});

And my data return from the ajax is in this form

<?php
$arr = [
    ["id" => 1, "text" => "Testing"],
    ["id" => 2, "text" => "test2"],
    ["id" => 3, "text" => "test3"],
    ["id" => 4, "text" => "test4"],
    ["id" => 5, "text" => "test5"]
];
echo json_encode($arr);
exit();
?>
发布评论

评论列表(0)

  1. 暂无评论