7

我有两个下拉选择下拉菜单:一个用于区域,一个用于所选区域中的城市。结果由 AJAX 加载,在我的响应中,我得到了 JSON 数组中的所有城市:

{
    1709: "Geertruidenberg", 
    1710: "Netersel", 
    1711: "Macharen", 
    1712: "Beers", 
    1713: "Hank", 
    1714: "Oudemolen", 
    1715: "Nistelrode"
}

我正在使用这个小插件在选择下拉列表中加载数据:

(function($, window) {
    $.fn.replaceOptions = function(options) {
        var self, $option;

        this.empty();
        self = this;

        $.each(options, function(index, option) {
            $option = $("<option></option>")
                .attr("value", index)
                .text(option);
            self.append($option);
        });
    };
})(jQuery, window);

而这段 javascript 来做 AJAX 请求:

$('select#Profile_regionId').change(function() {
    $.post('/ajax/getcities', {regionid: $(this).val()}, function(data){
        //console.log(data.cities);
        $("select#Profile_cityId").replaceOptions(data.cities);
    }, 'json');
});

一切都很好,除了城市下拉菜单自动按 JSON 数组键排序。我尝试为此使用 sort() 方法,但它不起作用,因为它是一个对象而不是数组。然后我尝试创建一个数组:

var values = [];
$.each(data.cities, function(index,value)) {
    values[index] = value;
}

但是由于某种原因,下拉列表会从 1 填充到该城市的第一个找到的 id(数组的键),我不知道它为什么这样做(数组本身看起来不错)。

我如何对事物进行排序,以便我的城市在下拉列表中按字母顺序排列?

4

3 回答 3

9

需要将其转换为数组,以便对其进行排序。假设这是您的对象。请注意,我将其重新排列为未排序,以证明这是有效的。

originalData = {
    1712: "Beers", 
    1709: "Geertruidenberg", 
    1710: "Netersel", 
    1713: "Hank", 
    1714: "Oudemolen", 
    1711: "Macharen", 
    1715: "Nistelrode"
};

现在要创建一个数组版本,我们需要创建一个数组,并将对象插入其中。我称这些键为“年”。请注意,我们在键上调用 parseInt。JavaScript 中的键(数组除外)总是字符串。例如,{foo: "bar"}有一个字符串键“foo”。这也适用于数字键。

var dataArray = [];
for (year in originalData) {
    var word = originalData[year];
    dataArray.push({year: parseInt(year), word: word});
}

有可能我们现在的数据无法排序,所以我们手动对其进行排序。请注意,这是区分大小写的排序。例如,“Qux”出现在“foo”之前。

dataArray.sort(function(a, b){
    if (a.word < b.word) return -1;
    if (b.word < a.word) return 1;
    return 0;
});

该函数现在只是从我们的数组中提取 option.year 和 option.word。

$.fn.replaceOptions = function(options) {
    var self, $option;

    this.empty();
    self = this;

    $.each(options, function(index, option) {
        $option = $("<option></option>")
            .attr("value", option.year)
            .text(option.word);
        self.append($option);
    });
};

然后你最终使用插件,传递数组。如果最适合您,您可以将所有这些代码放入插件中。

$('#mylist').replaceOptions(dataArray);

小提琴

于 2013-08-28T14:19:29.990 回答
3

这将做你想做的事并处理空的 ids/undefined 值:

var data = {
    1709: "Geertruidenberg", 
    1710: "Netersel", 
    1711: "Macharen", 
    1712: "Beers", 
    1713: "Hank", 
    1714: "Oudemolen", 
    1715: "Nistelrode"
};

var values = [];
$.each(data, function(index, value) {
    values[index] = value;
});

values.sort();

$.each(values, function(index, value) {
    if(value != undefined) {
        $("#Profile_cityId").append("<option>"+ value +"</option");
    }
});

只需用您自己的函数替换我输入的附加内容,因为 jsFiddle 给我使用它带来了麻烦。演示:http: //jsfiddle.net/R4jBT/3/

于 2013-08-28T14:20:38.923 回答
1

所以这就是我将如何做到的。我假设您收到的 AJAX 响应如下:

results: [
    {year: 1709, city: "Geertruidenberg"}, 
    {year: 1710, city: "Netersel"}, 
    {year: ..., city: ...} 
]

而且,在标准的 AJAX 调用中,您可以像这样在success函数中运行它们:

success: function(data) {
    var results = data.results;
    if (results.length > 0) {
        for (i=0; i < results.length; i++) {
         
            dataArrayOrig.push({
                "id" : results[i].year,
                "label" : results[i].city 
            });
        }
    }
},

我看到你说你是这样打电话的:

$.post('/ajax/getcities', {regionid: $(this).val()}, function(data){
    //console.log(data.cities);
$("select#Profile_cityId").replaceOptions(data.cities);}, 'json');

你没有做任何测试data来查看它是否有结果(例如if (data.length > 0) { ... }),你需要将这些结果推送到一个保持原始状态的原始数组和另一个可以排序的数组,然后是一个可以取回的最终数组原始年份到标签,然后下拉可以接收。

如果你按照我上面展示的那样做,你可以将我给出的线条整合到该function(data){ ... }区域中。

push在对象之后dataArrayOrig,您可以推送到一个可用于排序的新数组,使用比较函数来确定标签(城市)应该位于前一个条目之前还是之后:

    var results = data.results;
    if (results.length > 0) {
        for (i=0; i < results.length; i++) {
         
            dataArrayOrig.push({
                "id" : results[i].year,
                "label" : results[i].city
            });
            dataArraySorting.push({
                "id" : results[i].year,
                "label" : results[i].city
            });
            dataArraySorting.sort(compare);
            JSON.stringify(dataArraySorting); // sorted cities, but will be mismatched to the years
        }
    }

比较函数:

function compare (a, b) {
    if (a.label < b.label)
        return -1;
    if (b.label  < a.label)
        return 1;
    return 0;
});

您也可以内联执行此操作:

dataArraySorting.sort(function(a, b){
      if (a.label < b.label) return -1;
      if (b.label < a.label) return 1;
      return 0;
}); 

我更喜欢函数方法,因为它可以重复使用。我们将在一分钟内看到它的用处。

对于您的数组,在函数之前的顶部声明它们:

var dataArrayOrig = [];
var dataArraySorting = [];
var dataArraySorted = [];

因此,在遍历结果的循环之后,启动另一个遍历“排序”数组的循环,并将其标签与我们推送到的原始数组中的标签进行比较,然后取出原始 ID(年份):

for (var j=0; j < dataArraySorting.length; j++) {
    for (var k=0; k < dataArrayOrig.length; k++) {
        if (dataArraySorting[j].label == dataArrayOrig[k].label) {
            dataArraySorted.push({
                "id" : dataArrayOrig[k].id,
                "label" : dataArraySorting[j].label
            });
            console.log("Sorted ID: " + dataArrayOrig[k].id + ", Sorted label: " + dataArraySorting[j].label);
            dataArraySorted.sort(compare);
            JSON.stringify(dataArraySorted); // array of sorted cities, matched to year
        }
    }
}

您将继续dataArraySorted像往常一样将该数组应用于您的下拉列表。我测试了我是否从原始 AJAX 调用中获得了超过 0 个项目,然后我使用idlabel从数组的属性名称中附加了选项:

if (dataArraySorted.length > 0) {
    $.each(dataArraySorted, function() {
        $("#combobox").empty().append($("<option></option>").val(this['id']).html(this['label'));
    });
}

JSF处理结果。

于 2021-10-27T17:11:49.190 回答