javascript 使用 Select2 仅加载一次远程数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20701570/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 19:02:49  来源:igfitidea点击:

Loading remote data only once with Select2

javascriptjquery-pluginsweb

提问by Yaron

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

正如标题所暗示的,我只想加载一次远程数据。我想过使用独立的 ajax 调用加载数据并在控件中“本地”设置它,但想知道是否有更多的“内置”方式来做到这一点......

回答by Chris W

a solution can be found here:

可以在此处找到解决方案:

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

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.

我可能误解了你的问题。如果您希望一次加载所有数据,则使用 Select2,没有内置功能可以做到这一点。

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

您建议执行单个查询,然后在 Select2 中使用存储的数据将是可行的方法。

回答by Ska737

This is for Select2 v4.0.3:

这适用于 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.

我有同样的问题,并通过触发 AJAX 调用并使用返回的数据作为初始化数据数组来解决它。

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

这对我的想法很有效。希望这可以帮助人们搜索相同的问题。

回答by Tayyab Hayat

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

我从ajax返回的数据是这种形式

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

回答by seanp2k

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'

  • 您在 /services 有一个 REST API 端点,它提供一个 JSON 对象数组

  • 该数组包含至少具有“name”和“id”属性的对象。例子:

    [{"id": 0, "name": "Foo"}, {"id": 1, "name": "Bar"}]
    
  • 您想将该数组存储为全局“services_raw”

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

首先,我们的函数加载数据并创建全局“services_raw”(又名“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:

其次,我们的 Select2 实例化代码将我们的数据转换为 Select2 可以使用的格式:

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:

在调用上述函数之前,HTML 中的 Select2 元素应如下所示:

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

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

要使用所有这些,请调用(在 JS 中):

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

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

最后,这是一个 JSFiddle,您可以在其中玩类似的东西: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.

基本上,在我上面的示例中,我们只是使用 ajax 来填充 Fiddle 中的 window.pills 等效项。

Hope this helps :)

希望这可以帮助 :)

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

如果您知道如何通过 Select2 .ajax 函数执行此操作,请回复,因为这会更短一些。