0

我们编写了一个通用的 jQuery 动作,它绑定到一个选定的国家列表。绑定到国家选择;当它被改变时,调用服务器来获取状态......

$('#' + countryElementID).change(function () {
    var countryID = $('#' + countryElementID).val();
    $.ajax({
        type: 'POST',
        url: '/App/GetStatesByCountry',
        data: {
            id: countryID
        },
        dataType: 'json',
        success: function (result) {
            // build HTML replace via .html
        },
        failure: function (result) {
            // ...
        }
    });
});

这是触发此的代码...

var populateCompanyInfo = function (resultData) {

var populateList = {
    CompanyName: 'input',
    Address1: 'input',
    Address2: 'input',
    City: 'input',
    Zip: 'input',
    Email: 'input',
    Phone: 'input',
    Fax: 'input',
    CountryID: 'select',
    StateID: 'select',
    Active: 'toggle'
}

$.each(populateList, function (name, value) {
    var a = eval('resultData.' + name);
    var sectionID = 'RealtyCompany';
    if (a != null || a != '') {
        if (value == 'input') {
            // ...
        }
        if (value == 'select') {
                var a = eval('resultData.' + name);
                $('#select' + sectionID + name).val(a);
                $('#select' + sectionID + name).trigger('change');
        }
        if (value == 'toggle') {
            // ...
        }
    }
});

我遇到的问题是它在填充状态之前选择了 StateID(由 Country 下拉列表的更改触发)。

是否有一个变量可以在 Country 下拉列表的通用操作中传递,它基本上会等到变量传递?我试图想办法在 jQuery 中合并一个延迟操作,但我很难找到一种方法来做到这一点。

4

1 回答 1

0

看了一会儿后,便士掉了——我想我已经看透了这个问题。我是否写了有效的答案还有待观察。

无论您采用哪种方式,关键是让 jqXHR 的“承诺”(通过 AJAX 获取所选国家的州而产生)可用于其他范围。.data('fetchData')我选择通过设置强加于国家选择元素的 jQuery 对象的属性来做到这一点。

然后,由于.each(populateList, ...)循环的工作方式(我没有尝试更改它),jqXHR 还需要作为循环内两个分支之间的外部成员传递。可以使用其他方法,但我想到的所有方法至少都一样混乱。

由于.data()不能保证对象存在,因此需要相当大的安全性来增加脚本的体积。很有可能有一种更简单的方法可以用更少的代码实现相同的目的。

这是代码:

$(function() {
    var countryElementID = 'selectRealtyCompanyCountryID';
    $('#' + countryElementID).change(function () {
        var $this = $(this);
        var jqXHR = $.ajax({
            type: 'POST',
            url: '/App/GetStatesByCountry',
            data: { id: $this.val() },
            dataType: 'json',
            success: function (result) {
                // Build HTML replace via .html()
            },
            failure: function (result) {
                // Generic error handler
                alert('Generic error handler');
            }
        });
        var fetchData = $this.data('fetchStates');// May of may not exist.
        if(fetchData) fetchData.jqXHR = jqXHR;//Make the jqXHR available to other scopes via the DOM.
    });

    var populateCompanyInfo = function (resultData) {
        var populateList = {
            CompanyName: 'input',
            Address1: 'input',
            Address2: 'input',
            City: 'input',
            Zip: 'input',
            Email: 'input',
            Phone: 'input',
            Fax: 'input',
            CountryID: 'select',
            StateID: 'select',
            Active: 'toggle'
        }
        var fetchPromise = null;

        $.each(populateList, function (name, value) {
            var a = resultData[name];
            var sectionID = 'RealtyCompany';
            if(a) {
                if (value == 'input') {
                    // ...
                }
                if (value == 'select' && name == 'CountryID') {
                    //Branch for the CountryID select menu
                    var $el = $('#select' + sectionID + name);
                    var fetchData = $el.data('fetchStates');
                    if(!fetchData) {
                        $el.data('fetchStates', {});
                    }
                    if(fetchData.jqXHR && fetchData.jqXHR.abort) {//safety
                        fetchData.jqXHR.abort();//Kill any outstanding ajax requests of the same type.
                    }
                    $el.val(a).trigger('change');
                    fetchPromise = data.jqXHR;//Make the new jqXHR object available to the 'StateID' branch next time round the .each loop.
                }
                if (value == 'select' && name == 'StateID') {
                    //Branch for the StateID select menu
                    if(fetchPromise && fetchPromise.done) {//May of may not be defined.
                        fetchPromise.done(function(data, textStatus, jqXHR) {
                            // At this point the States element is freshly populated with states.
                            // Here, do whatever is necessary once the States element
                            // eg. set its .val() then trigger its 'change' event.
                        }).fail(function(jqXHR, textStatus, errorThrown) {
                            // Display error message?
                            // Set the States element to a default value?
                            alert('Specific error handler');
                        });
                    }
                }
                if (value == 'toggle') {
                    //...
                }
            }
        });
    }
});

经测试可消除语法错误 - 仅此而已

编辑

是的,它可以被简化——这里有一些更好的代码。由于 ajax 失败,您将看到错误消息 - 我还没有完全模拟获取状态。但是错误信息很好——它们意味着事件的顺序是正确的。

于 2013-03-14T02:47:17.120 回答