1. 程式人生 > >以申購單為例項,講解Jquery動態刪減行,新增行新增滑鼠事件,子視窗與父視窗傳值,自動計算金額,及輸入值的驗證,前臺資料批量提交到後臺action

以申購單為例項,講解Jquery動態刪減行,新增行新增滑鼠事件,子視窗與父視窗傳值,自動計算金額,及輸入值的驗證,前臺資料批量提交到後臺action

最近在為公司做一個小型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