Php 使用Ajax同时填充两个下拉列表

Php 使用Ajax同时填充两个下拉列表,php,javascript,ajax,Php,Javascript,Ajax,我有三个HTMLDropDownList()。第一个下拉列表包含类别,第二个包含不同产品的子类别,第三个包含品牌(或制造商) 选择一个类别时,应根据传递给Ajax函数的类别id,从数据库中立即填充两个下拉列表subcategory和brand。我正在使用以下Ajax代码 function ajax() { if(window.XMLHttpRequest) { xmlhttp=new XMLHttpRequest(); } else {

我有三个HTML
DropDownList
)。第一个
下拉列表包含类别,第二个包含不同产品的子类别,第三个包含品牌(或制造商)

选择一个类别时,应根据传递给Ajax函数的类别id,从数据库中立即填充两个下拉列表subcategory和brand。我正在使用以下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();             
}   
选择类别时,将调用执行Ajax请求的
getSubcategoryList(selected)
Javascript函数。问题是,我需要同时填充“子类别”和“品牌”下拉列表(当选择类别时)

它正在工作,并且根据传递的类别id立即填充两个下拉列表(它是上述所选函数的参数<代码>

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


为什么会发生这种情况?解决方案是什么?

我认为第二个ajax()调用删除了xmlhttp变量。当你把你的警报放进去时,我敢打赌这是在第一次打电话之前完成第二次。您可能应该更早地调用ajax(),并从处理程序中删除该调用。

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

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();             
}
@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);
}

我建议你用这个

 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请求返回包含选项的字符串,例如
子类别1subcategory2
等。并且您希望根据选定的子类别而不是选定的类别加载品牌

我想您可以使用回拨功能。但我确实建议使用jquery。这要简单得多。您不需要手动执行所有操作。(创建XHTPrequest对象并维护响应状态以及所有那些笨拙的activex对象相关操作)

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

xmlhttp
设置为本地不起作用。我试过了(和你说的一样),也试过同样的方法使用jQuery,但仍然不走运。我试过了,但不得不悲哀地说,它产生了同样的问题。我同意这一点。在进行子类别列表调用之前,没有理由期望get brand list请求已经完成。警报框允许调用同步完成。您需要在这里强制同步,因为第二次调用取决于第一次调用的结果。一般来说,我会使用回调函数来实现这一点,该函数仅在第一次调用返回后才显式地进行第二次调用。此外,我相信,通过使用单个全局XHMLHTTP变量,如果连续进行,任何要进行同步的请求也可能失败。已成功完成。这可能很简单,但我想不出来。非常感谢您抽出时间。我学到了一些新东西。