【问题标题】:Populating two dropdowns at once using Ajax使用 Ajax 一次填充两个下拉列表
【发布时间】:2012-06-04 04:10:57
【问题描述】:

我有三个 HTML DropDownList (<select><option></option></select>)。第一个DropDownList 包含类别,第二个包含不同产品的子类别,第三个包含品牌(或制造商)。

选择一个类别后,应根据传递给 Ajax 函数的类别 ID 一次从数据库中填充两个下拉子类别和品牌。我正在使用以下 Ajax 代码。

function ajax()
{
    if(window.XMLHttpRequest)
    {
        xmlhttp=new XMLHttpRequest();
    }
    else
    {
        xmlhttp = new ActivexObject("Microsoft.XMLHTTP");
    }
}

function getBrandList(selected)  //selected is the category id.
{               
    ajax();
    xmlhttp.onreadystatechange=function()
    {
        if(xmlhttp.readyState==4 && xmlhttp.status==200)
        {
            document.getElementById("brandList").innerHTML=xmlhttp.responseText;            
        }
    }

    xmlhttp.open("GET","ajax/BrandAjax.php?selected="+selected, true);
    xmlhttp.send();     
    alert(selected);            
}

function getSubcategoryList(selected) //selected is the category id.
{                       
    getBrandList(selected); //First above function is invoked to populate brands.
    ajax();
    xmlhttp.onreadystatechange=function()
    {
        if(xmlhttp.readyState==4 && xmlhttp.status==200)
        {
            document.getElementById("subCategoryList").innerHTML=xmlhttp.responseText;                              
        }
    }

    xmlhttp.open("GET","ajax/SubCatAjax.php?selected="+selected, true);
    xmlhttp.send();             
}   

当一个类别被选中时,getSubcategoryList(selected) Javascript 函数被调用来执行 Ajax 请求。问题是我需要同时填充子类别和品牌下拉列表(选择类别时)。

它正在工作,并且根据传递的类别 ID 一次填充两个下拉列表(它是上述函数 selected 的参数)。

我不必要地使用了函数getBrandList() 底部的警告框。注释此警告框时,仅填充一个下拉菜单,即子类别。品牌仍然是空的。我不再需要这个警报框了。

为什么会这样?解决办法是什么?

【问题讨论】:

    标签: php javascript ajax


    【解决方案1】:

    我认为第二个 ajax() 调用正在清除 xmlhttp 变量。当您发出警报时,我敢打赌它会给第一个呼叫时间在开始第二个呼叫之前完成。您可能应该更早地调用 ajax() 并从您的处理程序中删除该调用。

    【讨论】:

    • 我同意这一点。没有理由期望在调用子类别列表之前完成获取品牌列表请求。警报框允许调用同步完成。您需要在此处强制同步,因为第二次调用取决于第一次调用的结果。一般来说,我会使用一个回调函数来执行此操作,该函数仅在第一个调用返回后才显式进行第二次调用。
    • 此外,我相信通过使用单个全局 XHMLHTTP 变量,如果连续发出任何想要异步的请求,也可能会失败。
    【解决方案2】:

    首先,建议您为此尝试一些现代 JavaScript 框架,例如 JQuery。

    @tzerb 怎么说:在第一个 AJAX 请求完成之前覆盖全局变量 xmlhttp。您必须为此使用局部变量。

    function ajax()
    {
        var xmlhttp; //!!
        if(window.XMLHttpRequest)
        {
            xmlhttp=new XMLHttpRequest();
        }
        else
        {
            xmlhttp = new ActivexObject("Microsoft.XMLHTTP");
        }
        return xmlhttp; //!!
    }
    
    function getBrandList(selected)  //selected is the category id.
    {               
        xmlhttp = ajax(); //!!
        xmlhttp.onreadystatechange=function()
        {
            if(xmlhttp.readyState==4 && xmlhttp.status==200)
            {
                document.getElementById("brandList").innerHTML=xmlhttp.responseText;            
            }
        }
    
        xmlhttp.open("GET","ajax/BrandAjax.php?selected="+selected, true);
        xmlhttp.send();     
        //alert(selected);            
    }
    
    function getSubcategoryList(selected) //selected is the category id.
    {                       
        getBrandList(selected); //First above function is invoked to populate brands.
        xmlhttp = ajax(); //!!
        xmlhttp.onreadystatechange=function()
        {
            if(xmlhttp.readyState==4 && xmlhttp.status==200)
            {
                document.getElementById("subCategoryList").innerHTML=xmlhttp.responseText;                              
            }
        }
    
        xmlhttp.open("GET","ajax/SubCatAjax.php?selected="+selected, true);
        xmlhttp.send();             
    }
    

    使用 JQuery,您的代码可能如下所示:

    function getBrandsList(selected){
        $("#brandList").load("ajax/BrandAjax.php?selected="+selected);
    }
    function getSubcategoryList(selected){
        $("#brandList").load("ajax/SubCatAjax.php?selected="+selected);
    }
    

    【讨论】:

    • 使xmlhttp 本地化不起作用。我试过了(和你说的一样),也试过用 jQuery 还是没有运气。
    【解决方案3】:

    seriyPS 基本上就在这方面达到了目标。问题实际上是 xmlhttp 变量。您需要在它正在使用的每个函数中将其声明为本地。基本上,为函数调用创建一个闭包。然而,问题不一定是它需要是“本地的”,而是由于它是一个全局变量,它在第二个请求中被重新定义。这实际上会终止初始请求,因为变量现在指向第二个请求。

    警告框使其工作的原因是因为第一个请求在您可以“单击”确定之前完成了 ajax 请求。 (警告框会暂停 javascript 的执行,因此会延迟第二个请求,直到您单击确定之后。)

    要解决此问题,您可以修改代码以对每个请求使用不同的变量。尝试将您的功能更改为以下内容:

    // Global Variables
    var brandListRequest;
    var subcategoryRequest;
    
    function ajax()
    {
        var xmlhttp; //!!
        if(window.XMLHttpRequest)
        {
            xmlhttp=new XMLHttpRequest();
        }
        else
        {
            xmlhttp = new ActivexObject("Microsoft.XMLHTTP");
        }
        return xmlhttp; //!!
    }
    
    function getBrandList(selected)  //selected is the category id.
    {               
        brandListRequest = ajax(); //!!
        brandListRequest.onreadystatechange=function()
        {
            if(brandListRequest.readyState==4 && brandListRequest.status==200)
            {
                document.getElementById("brandList").innerHTML=brandListRequest.responseText;            
            }
        }
    
        brandListRequest.open("GET","ajax/BrandAjax.php?selected="+selected, true);
        brandListRequest.send();     
        //alert(selected);            
    }
    
    function getSubcategoryList(selected) //selected is the category id.
    {                       
        getBrandList(selected); //First above function is invoked to populate brands.
        subcategoryRequest = ajax(); //!!
        subcategoryRequest.onreadystatechange=function()
        {
            if(subcategoryRequest.readyState==4 && subcategoryRequest.status==200)
            {
                document.getElementById("subCategoryList").innerHTML=subcategoryRequest.responseText;                              
            }
        }
    
        subcategoryRequest.open("GET","ajax/SubCatAjax.php?selected="+selected, true);
        subcategoryRequest.send();             
    }
    

    【讨论】:

    • 成功完成。这可能很简单,但我无法弄清楚。非常感谢您的宝贵时间。学到了一些新东西。
    【解决方案4】:

    我建议您为此使用jQuery

     1. Load the first dropdown with categories on page load
     2. Call the following ajax call on change event of the first dropdown, categoryList
        $('#categoryList').change(function () {
          $('#subCategoryList').load("ajax/SubCatAjax.php?selected="+this.value);
          $('#brandList').load("ajax/BrandAjax.php?selected="+$('#subCategoryList').val());
        });
     3. Call the following ajax call on change event of the second dropdown, subcategoryList.
        $('#subCategoryList').change(function () {
          $('#brandList').load("ajax/BrandAjax.php?selected="+this.value);
        });
    

    附:我假设您的 ajax 请求返回包含选项的字符串,例如。 <option value='1'>subcategory1</option><option value='2'>subcategory2</option> ..等等。并且您想根据所选子类别而不是所选类别加载品牌。

    【讨论】:

    • 我试过了,但不得不遗憾地说它产生了同样的问题。
    【解决方案5】:

    我想你可以使用回调函数。但我确实建议使用 jquery。它简单了很多。您不需要手动完成所有操作。(创建 xhttprequest 对象并维护响应状态以及所有那些笨拙的 activex 对象相关的事情)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-08
      相关资源
      最近更新 更多