联动下拉菜单 AjaxPro + JS
因为在项目的发票管理中,用户要求在弹出的对话框(网页)中选择单位后,返回原来页面,并且将单位值填充进来!
实际上 单位的 选择涉及三个部分:
单 位<span style="color:Red">*</span></td>
<td style="height: 30px" >
<input id="inp_iComId" type="hidden" name="inp_iComId" runat="server" />
<asp:textbox id="tb_vComName" runat="server" Width="80%" ReadOnly="true"></asp:textbox>
<a onclick="return SelectCompany();" href="#"><img src="Images/search.gif" style="border:0" alt="检索" /></a>
<asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" ControlToValidate="tb_vComName"
Display="Dynamic" ErrorMessage="*"> </asp:RequiredFieldValidator>
</td>
2、textbox保存单位名称
3、img单击弹出对话框
本例中代码涉及比较多,所以只贴出相关代码:
该页面中,js selectCompany和相关函数
function Unable(){
//document.getElementById("<%=ddl_iConId.ClientID%>").disabled="disabled" ;
}
function SelectCompany()
{
document.getElementById("<%=ddl_iConId.ClientID %>").disabled=false;
var window_height = 500;
var window_width = 800;
var top = (window.screen.availHeight-window_height)/2;
var left = (window.screen.availWidth-window_width)/2;
var fileName = "OpenWindow.aspx?title='请选择单位'&controlName=SelectCompany&ctrlid=<%=inp_iComId.ClientID%>&ctrlnameid=<%=tb_vComName.ClientID%>";
window.open(fileName,"","left="+left+",top="+top+",height="+window_height+",width="+window_width+",resizable=yes,scrollbars=yes,status=no,toolbar=no,menubar=no,location=no");
}
var comid;
function ReRender()
{
alert("1");
icomid=document.getElementById("<%=inp_iComId.ClientID %>").value;
//每次比较 comid是否为新值,如果为新就重新绘制select
if((icomid!="")&&(icomid!=comid)){
PitchWeb.Modules.Balance.InvoiceBillForm.GetContract(icomid,CreateDropDownList);
}
comid=icomid;
}
function CreateDropDownList(res)
{
if(res.error) return alert("AjaxPro发生错误\n" + res.error.Message);
if(res==null) return;
var sel=document.getElementById("<%=ddl_iConId.ClientID %>");
var tbl=res.value;
if(sel.options.length>1)
sel.options.length=1;
//刷新select选择菜单
for(var i=0;i<tbl.Rows.length;i++){
var op=document.createElement("option");
op.setAttribute("value",tbl.Rows[i]["Id"]);
op.setAttribute("text",tbl.Rows[i]["vCode"]);
//alert(op.text + ":" + op.value);
sel.options.add(op);
}
}
</script>
在该页的cs文件中:
引用了AjaxPro.dll
public DataTable GetContract(string icomid)
{
DataTable dt = null;
try
{
string companyname=ShowHelper.GetCompanyNameById(icomid);
PitchWeb.Contract contract1 = BillFactory.CreateContract(BillTypes.UnYield);
if (icomid != "")
dt =contract1.GetConByCom(icomid);
return dt;
}
catch (Exception ce)
{
return dt;
}
finally
{
}
}
在被打开的对话框中(openwindow中)
var ctrlValue //传递的主键参数
var ctrlNameValue
function GetDetail(sid,sName)
{
ctrlValue = sid;
ctrlNameValue = sName;
}
function returnopen(retbutton,retnamebutton,retvalue,retnamevalue)
{
window.opener.document.all(retbutton,0).value=retvalue;
window.opener.document.all(retnamebutton,0).value=retnamevalue;
window.opener.document.all(retnamebutton,0).focus();
window.opener.ReRender(); //添加者:周翔;用以回调刷新select控件
window.close();
}
</script>
在向父窗体中赋值以后,就可以调用父页中的函数ReRender(); 来重新绘制Selector下拉列表;
本例中调用了 ajaxpro但是具体的配置很简单,关键是要了解 ajaxpro在js和c#类型 type之间如何调用的关系:
比如我要是想连续初始化多个数据部分,比如说:重新绘制两个Select控件(dropdownlist在客户端的控件)
我就可以返回一个dataset
然后在 callback(res)函数中
可以这样得到 DataTable在js中的对象
var ds = res.value;
var tbl = ds.Tables[0];
然后再调用 就可以了!
但是,注意的是在ds中添加数据表 DataTable的时候,可能会遇到DataTable已经被另一个DataSet包含的错误;
我的服务端c#代码是这么写的:
public DataSet GetContract(string icomid, string isortid)
{
DataSet ds = new DataSet("DS");
DataTable dt = null;
try
{
string companyname = System.Web.HttpContext.Current.Server.UrlEncode(ShowHelper.GetCompanyNameById(icomid));
PitchWeb.Contract contract1 = null;
PitchWeb.Plan plan1 = null;
if (isortid == "2")
{
contract1 = BillFactory.CreateContract(BillTypes.Yield);
plan1 = BillFactory.CreatePlan(BillTypes.Yield);
}
else
{
contract1 = BillFactory.CreateContract(BillTypes.UnYield);
plan1 = BillFactory.CreatePlan(BillTypes.UnYield);
}
if (icomid != "")
dt = contract1.GetConByCom(icomid);
dt.TableName = "con";
ds.Tables.Add(dt.Copy());
DataTable dt2 = new DataTable();
dt2.Columns.Add("vComName", typeof(System.String));
dt2.Rows.Add(companyname);
ds.Tables.Add(dt2);
DataTable dtplan = plan1.GetPlanByCom(icomid);
ds.Tables.Add(dtplan.Copy());
return ds;
}
catch (Exception ce)
{
return ds;
}
finally
{
}
}
其实Ajaxpro在使用的时候可以根据服务端返回的对象灵活使用,具体的问题下面会描述:
Ajaxpro的效率就是很大的问题;
我曾经在一个AjaxPro的CallBack函数后面紧跟了另一个Ajaxpro的js请求函数;
结果发现没有响应,怎么调试都不行;后来发现在那个请求结束时,添加 alert("!!")提示框就可以了?(到现在无解)
但是,即使那个请求的CallBack函数有响应,却发生了新的问题;
发现第一个CallBack成功执行;
第二个CallBack执行填充的下拉菜单,Asp.NET不能识别填充的 options
Html里面明明是有options;但是就是在服务端的 XXX . SelectedValue="" 取不到值;
最后没有办法了,将两级关系统统放到服务端,然后返回一个DataSet(这个东西就像一个包,什么都可以往里面放)
在客户端读取的代码:(只有部分)
function ReBindContract(){
var iplanid=document.getElementById("<%=ddl_iOldPlan.ClientID %>").value;
/* 明细表单中 PostToParent 为优先赋值单位名称 追加计划编号;*/
var PostToBody=document.getElementById("PostToParent");
PostToBody.value=PostToBody.value+"&iPlanId=" + iplanid;
if((iplanid!=planid)&&(comid!="")&&(iplanid!="")&&(sortid!=""))
PitchWeb.Modules.Balance.AdjustBillForm.GetConId(iplanid,comid,sortid,DisplayContrList);
}function DisplayContrList(res){
if(res.error) return alert("AjaxPro发生错误\n" + res.error.Message);
if(res==null) return;
var ds=res.value;
var tbl=ds.Tables[0].Rows[0]["conid"];
if((tbl!=conid)&&(tbl!="")&&(tbl!=null))
{
document.getElementById("<%=iConId.ClientID %>").value=tbl;
conid=tbl;
}
tbl=ds.Tables[1];
var sel=document.getElementById("<%=ddl_iNewPlan.ClientID %>");
ReBindList(sel, tbl);
}
/*几乎通用的Ajaxpro绑定下拉菜单js函数*/
function ReBindList(sel,tbl)
{
if(sel.options.length>1)
sel.options.length=1;
//刷新select选择菜单
for(var i=0;i<tbl.Rows.length;i++){
var op=document.createElement("option");
op.setAttribute("value",tbl.Rows[i]["Id"]);
op.setAttribute("text",tbl.Rows[i]["vCode"]);
//alert(op.text + ":" + op.value);
sel.options.add(op);
}
}
代码很乱,就提到这里了吧!
留个问题给大家:ajaxpro怎么应用web窗体下的变量(this.Somevariable)?