以申购单为实例,讲解Jquery动态删减行,新增行添加鼠标事件,子窗口与父窗口传值,自动计算金额,及输入值的验证,前台数据批量提交到后台action

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Wallbanger/article/details/8250420

最近在为公司做一个小型ERP,其中有一个申购模块,公司需求大概:新建申购单,新建时添加要申购的物料信息。输入每样物料的申购数量,预计价格,前台自动计算总价。

设计需求大概:申购单应可以动态增减物料信息。每条物料信息应验证不可重复。大概就是这些。本人刚刚毕业,参考网上资料后,我的设计是这样的,欢迎大家指点交流。

引入Jquery文件

首先有一个table(简化参数),id为dataTable

<table id="dataTable">
<tr>
<td style="background-color:#4682B4; font-weight:bold; color:#FFFFFF; height:25px;" colspan="6">物料信息
<input type="button" onclick="add()" value="+"/>
</td>
</tr>
<tr>
<th>物料名称</th>
<th>规格型号</th>
<th>申购数量</th>
<th>计量单位</th>
<th>预计价格</th>
<th>总价</th>
</tr>
</table>

button原本是一个加号的小图片,这里暂时用button代替。下面是触发onclick事件

function add(){//这里添加物料信息是以弹出子窗口查询的方式,会弹出一个子窗口,用于分页显示系统预先添加好的所有物料,每样物料后有一个添加按钮,点击后以a数组传值到父窗口。跟着用Jquery添加一行。将a数组传过来的值(即选择的物料信息)赋值到新增行
var url ="wuliao.do";
var a = window.showModalDialog(url,window,"dialogWidth:500px;dialogheight:650px");
//这里先放下不说,我们看子窗口传值


这里的url用的是struts2.查询数据库的物料信息列表后返回物料查找页面,即子窗口。代码如下:

<table align="center" cellpadding="0" cellspacing="0" class="table_list">
<tr>
<th>物料名称</th>
<th>规格型号</th>
<th>操作</th>
</tr>
<c:if test="${empty materialInfoFromBeanList }">
<tr>
<td colspan="3" align="center">
没有符合条件的记录
</td>
</tr>
</c:if>
<c:forEach items="${materialInfoFromBeanList }" 
var="materialFromBean"  varStatus="status">
<tr>
<td>
${materialFromBean.material_name }</td>
<td>${materialFromBean.material_model }
</td>
<td>${materialFromBean.material_type }
</td>
<td>${materialFromBean.material_num }
</td>
<td>
<input type="hidden" id="${materialFromBean.material_id }name" value="${materialFromBean.material_name }"/>
<input type="hidden" id="${materialFromBean.material_id }model" value="${materialFromBean.material_model }"/>
<input type="hidden" id="${materialFromBean.material_id }unit" value="${materialFromBean.material_unit }"/>
<a href='#' onclick="jInsert('${materialFromBean.material_id }')">添加</a></td>
</tr>


这里用到了jstl标签,来迭代输出后台Action穿过来的物料list列表。如何试用struts,Action,传值就不讲了。物料过多时用分页,当然还要有查询条件,这里要说,如果有查询条件,再次查询请求Action。返回的数据会在新的窗口返回。解决办法是,在子窗口页面标题处添加

<base target="_self">


这样重新请求的数据就会返回当前页面。继续讲子窗口的传值。

父窗口需要的值是物料id,物料名称,规格型号,及计量单位

这里由于子窗口较小。而物料名称,规格型号等长度不定,所以不用input显示物料信息。而将要传递的值放在隐藏的input里。为区分每一种物料。这里以数据库物料信息的id做为物料名称,规格型号,及计量单位的前缀。后面的添加按钮的jInsert()事件传递物料的id值,这样就知道是取哪条物料的信息传递到前台了。

jInsert()代码

function jinsert(obj){
var xname = document.getElementById(obj+'name').value;
var xmodel = document.getElementById(obj+'model').value;
var xunit = document.getElementById(obj+'unit').value;
var a = new Array(obj,xname,xmodel,xunit);
window.returnValue = a;
window.close()
}

还有一个取消按扭

function jclose(){
var a = new Array();
window.returnValue = a;
window.close()
}

这样父窗口接收到子窗口的数组传值,继续讲刚才的add()

if(a[0]!=null&&a[0]!=''){//如果传递过来的a数组有值才进行添加行操作
$("#dataTable tr:last").after(//为dataTable的最后一行tr添加html元素
"<tr id='deletetr"+a[0]+"'><td>"+
"<input type='hidden' name='sg_xx_mat_ids' value='"+a[0]+"'/>"+a[1]+"</td><td>"+a[2]+"</td>"+
"<td><input type='text' name='sg_xx_nums' id='snum+"a[0]"'/></td><td>"+a[3]+"</td>"+
"<td><input type='text' name='sg_xx_prices' id='sprice+"a[0]"'/></td>"+
"<td><input type='text' id='sz+"a[0]"' readonly/></td></tr>")

这里要注意的是,添加的html元素代码太长肯定要换行的,换行需要在末尾添加冒号加号"+新起行开头要添加冒号",括号收尾。

这样在dataTable末尾就新增了一行,子窗口选择的数据也相应传递到了新增行。这里为了区分不同行,同样以物料id即a[0]区分。tr的id用于动态删减行,num和price,总价列对应的id用于动态计算总价用。隐藏域隐藏物料的name='sg_xx_mat_ids',及其它input的name属性,用于保存申购单时保存物料信息,这里如何批量提交数据到Action后台,先不讲。

隐藏域隐藏物料的name='sg_xx_mat_ids'同样为了控制不添加重复物料。控制方法,再在判断完a[0]数据是否为空后再做唯一性的判断。

var ids = document.getElementsByName('sg_xx_mat_ids');//取出当前添加的所有物料id数组

自定义js数组是否包含的函数

function in_array(ar,ch){//专用于弹窗与父窗口传值时判断是否表单里已经选择了此记录 ar 表示表单数据组成的数组,ch表示新添加进来的数据
var inflag = true;
if(ar.length==0){//如果ar即当前表单的物料id还没有数据,那就不用验证了。true
	inflag = true;
}else{//如果ar有物料id数据,则循环验证新添加的id是否包含在当前表单的数组里
	for (var i = 0; i < ar.length; i++) {
        if (ar[i].value == ch) {//注意ar是html元素数组,要取其value值进行比较
            	inflag = false;
	  }
        }
}
return inflag
}


add()函数变为

if(a[0]!=null&&a[0]!=''){//如果传递过来的a数组有值才进行添加行操作
var ids = document.getElementsByName('sg_xx_mat_ids');//取已添加的物料id
if(in_array(ids,a[0])){//是否重复添加
$("#dataTable tr:last").after(//为dataTable的最后一行tr添加html元素
"<tr id='deletetr"+a[0]+"'><td>"+
"<input type='hidden' name='sg_xx_mat_ids' value='"+a[0]+"'/>"+a[1]+"</td><td>"+a[2]+"</td>"+
"<td><input type='text' name='sg_xx_nums' id='snum+"a[0]"'/></td><td>"+a[3]+"</td>"+
"<td><input type='text' name='sg_xx_prices' id='sprice+"a[0]"'/></td>"+
"<td><input type='text' id='sz+"a[0]"' readonly/></td></tr>")

然后我们添加删除事件。

$("#deletetr"+a[0]).dblclick(function(){//对单行双击触发
	     	if(confirm("确认删除此条?")){
	     	$(this).remove();
			return true;
				}else {
			return false;
				 }
     })

这里选择如何触发就自定义了。我选择的是对单行双击,你也可以在每行添加一个删除按钮。或其它的jquery鼠标事件触发。

有人问为什么不在添加html元素时顺便就写上ondoubleclick="delete()"然后写一个delete()函数供调用。这个方法有的浏览器可以,但我用的ie6浏览器上不起作用。ie其它版本没有试。所以我试用的是用jquery添加触发事件的方法。兼容所有浏览器。

然后添加数量和预计价格自动计算总价的事件代码如下:

$("#snum"+a[0]).change(function(){
             	var n = $(this).val();
             	var p = $("#sprice"+a[0]).val()
             	$("#sz"+a[0]).(attr("value",n*p);
             })
$("#sprice"+a[0]).change(function(){
             	var n = $("#snum"+a[0]).val();
             	var p = $(this).val();
             	$("#sz"+a[0]).(attr("value",n*p);
             })

这里的触发事件我用的是Jquery的change.你可以自定义。有a[0]即物料id做区分。没有重复物料。可以很好的完成计算工作。

说明:这些添加的事件是包含在整个add()函数中的。最终版本

function add(){
var url =...
var a=...
if(a[0]!=null&&a[0]!=''){
var ids = ...
if(in_array(ids,a[0])){
$("#dataTable tr:last").after(...)
$("#deletetr"+a[0]).dblclick(...)
$("#sum"+a[0]).change(...)
$("#sprice"+a[0]).change(...)
}else{alert("此物料已添加")}
}}


然后是验证输入的信息,有个提交按钮触发提交前验证

functions checkSubmit(){
$('input[type=text]').each(function(){//如果添加物料过多,提示错误信息用户却不知道哪里错了,可以为输入错误的input的框添加红色背景,这里先为所有input添加点击消除背景色事件。这样用户发现错误信息重新编辑时可以消除红色背景提示。
    $(this).click(function(){
    	$(this).css({"background-color":"#fff"});
    	 })
  });
var datas = $("#dataTable tr").size();//取dataTable的行数
if(datas<=2){//验证是否添加了物料信息
$("#errorMsg").text("请添加申购物料!");
return;
}
var nums = document.getElementsByName('sg_xx_nums');
var prices = document.getElementsByName('sg_xx_pr_prices');
for(var s=0;s<=datas-3;s++){
     if(nums[s].value==''){
	$("#errorMsg").text("请输入申购数量");//errorMsg为表单下方一个id为errorMsg的span。用于提示出现的错误信息
	nums[s].style.background=="red";
	return;
	}
     if(!/^[0-9]*[1-9][0-9]*$/.test(nums[s].value)){//验证大于0的整数
	$("#errorMsg").text("请输入正确的申购数量");
	nums[s].style.background="red";
	return;
         }
     if(nums[s].value.length>10){
	$("#errorMsg").text("申购数量输入过长");
	nums[s].style.background="red";
	return;
	}
}//这里省略price的验证,同理num。
$("#errorMsg").text("");//如果前面验证都通过,先将errorMsg错误提示信息置空
if(confirm("确认填写无误提交?")){  $("#errorMsg").text("提交中...");
$('#dataform').submit();//提交form  
}else{ 
return;}
}


多行批量提交到后台Action,要提交的数据有物料id,申购数量,预计价格。后台action添加3个数组参数。并添加get,set方法

private String[] sg_xx_mat_ids;//申购物料id
private String[] sg_xx_nums;//申购数量
private String[] sg_xx_prices;//预计价格
//get...set...略

这样后台就可以接收到前台批量提交的数据。大概就是这些,第一次做文章,讲的有点乱。

文章完全通过网上参考学习,自己原创。有不足之处欢迎指出,一起交流学习。

Java学习交流群:    2177712

猜你喜欢

转载自blog.csdn.net/Wallbanger/article/details/8250420