展示:
图例说明:这个表格在模态框表单中,提交表单,将数据插入数据库。
需求说明:我的情景是一对多,表单填主表数据,表格写从表数据。页面为主表的数据列表,后边为编辑按钮,点击编辑弹出模态框(当然页面也有添加按钮,点击同样弹出模态框,实现新建功能)
技术栈:ajax、js、javaweb的表现层controller、H5、(bootsrap不重要)
现在说一下代码的实现:
增加:
模态框里有内容和一个表格(只有头),点击增加按钮js增加一行表格(多次点击增加多条),td内置input,填入数据,点击保存,js获取所有数据,发送给controller,存入数据库。
删除:
点击删除按钮,直接发送请求携带从表数据id,删除(删除按钮的点击事件其实可以将id放数组里,再点击保存时完整的去数据库修改主和从表,因为当时着急,没有想到,以后有机会再写吧。)
回显:
动态插入表格,将数据放入
一、增加代码如下
bootstrap模态框 重点在table (其他位置保留,方便理解)
<!-- 模态框(Modal) -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModallabel" aria-hidden="true"
data-backdrop="static" data-keyboard="false">
<div class="modal-dialog" style="width: 60%">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModallabel">添加生产成品</h4>
</div>
<div class="modal-body">
<fieldset>
<form class="form-horizontal" id="myform" role="form" action="" method="post">
<div class="form-group">
<label class="col-sm-2 control-label">设备编号
</label>
<div class="col-sm-10">
<input class="form-control" id="devNum" name="devNum" type="text">
<span style="color: red" id="col"></span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">设备类型
</label>
<div class="col-sm-10">
<select id="devType" class="form-control" name="devType">
<c:forEach items="${listBydev}" var="ls">
<option>${ls.devType}</option>
</c:forEach>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">客户公司
</label>
<div class="col-sm-10">
<select id="customerUnitId" class="form-control" name="customerUnitId">
<c:forEach items="${customerUnits}" var="cu">
<option value="${cu.id}">${cu.companyName}</option>
</c:forEach>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">负责人:</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="personCharge" id="personCharge"
value="<%=request.getSession().getAttribute("username")%>" readonly>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">日期
</label>
<div class="col-sm-10">
<input class="form-control" id="createDate" name="createDate" type="text" readonly>
</div>
</div>
<table class="table table-striped table-hover table-bordered" border="1px;">
<thead class="thead-light">
<tr class="proSon">
<td colspan="1">序号</td>
<td>内容</td>
<td>数量</td>
<td>进度</td>
<td>创建时间</td>
<td>备注</td>
<td>
<button type="button" class="btn btn-success btn-sm" onclick="addProSon()">增加</button>
</td>
</tr>
</thead>
<tbody id="proSon">
<%--如果是一个页面,并且使用jsp,那这样回显更好
<c:forEach items="${finProSonList}" var="ProSon">
<tr>
<td colspan="1">${ProSon.ordinal}</td>
<td>${ProSon.content}</td>
<td>${ProSon.amount}</td>
<td>${ProSon.schedule}</td>
<td>${ProSon.remarks}</td>
<td>${ProSon.createDate}</td>
<td>
<input type="button" value="删除" class="btn btn-danger btn-sm" onclick="del(${ProSon.id})">
</td>
</tr>
</c:forEach>--%>
</tbody>
</table>
<div class="form-group">
<label class="col-sm-2 control-label">
备注
</label>
<div class="col-sm-10">
<textarea class="form-control" rows="3" id="remarks" name=remarks></textarea> </div>
</div>
<input type="hidden" name="id" id="id"/>
</div>
</form>
</fieldset>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" id="upDev" class="btn btn-primary">提交更改</button>
<button type="button" id="addDev" class="btn btn-primary" onclick="create()">保存</button>
</div>
</div>
</div>
</div>
</div>
js
1、增加表格行的按钮点击方法
function addProSon() {
//创建tr元素
var trElemnet = document.createElement("tr");
//创建td元素
var td1Element = document.createElement("td");
var td2Element = document.createElement("td");
var td3Element = document.createElement("td");
var td4Element = document.createElement("td");
var td5Element = document.createElement("td");
var td6Element = document.createElement("td");
var td7Element = document.createElement("td");
//将数据添加到td元素
// td1Element.innerHTML = "";
td2Element.innerHTML = "<input class='form-control content' >";
td3Element.innerHTML = "<input class='form-control amount' type='number'>";
td4Element.innerHTML = "<input class='form-control schedule' >";
td5Element.innerHTML = "<input class='form-control createDate' type='date'>";
td6Element.innerHTML = "<input class='form-control remarks' >";
//创建按钮
var delElement = document.createElement("input");
delElement.type = "button";
delElement.value = "删除";
delElement.className = "btn btn-danger btn-sm";
//为按钮添加单击事件
delElement.onclick = function () {
//删除按钮所在的tr对象
trElemnet.parentNode.removeChild(trElemnet);
};
td7Element.appendChild(delElement);
//将td元素添加到tr元素中
trElemnet.appendChild(td1Element);
trElemnet.appendChild(td2Element);
trElemnet.appendChild(td3Element);
trElemnet.appendChild(td4Element);
trElemnet.appendChild(td5Element);
trElemnet.appendChild(td6Element);
trElemnet.appendChild(td7Element);
//将tr元素添加到tbody元素中
// let products = document.getElementById("products");
// document.getElementById("mytable").insertBefore(trElemnet,products);
document.getElementById("proSon").appendChild(trElemnet);
}
===========================================================================
2、表单提交按钮的触发方法:ajax发送数据进行保存
var add = [];
function create() {
$("#proSon input:text,input[type=number],input[type=date]").each(
function () {
var val = $(this).val();
// console.info(val);
add.push(val);
}
);
// console.info(add);
var addpush = [];
if (add.length != 0) {
var countInLine = 5;//一行几个数
for (var i = 0; i < add.length; i++) {
if (i % countInLine == 0) {
var obj = new Object();
obj.content = add[i];
obj.amount = add[i + 1];
obj.schedule = add[i + 2];
obj.createDate = add[i + 3];
obj.remarks = add[i + 4];
addpush.push(obj);
}
}
// console.info(addpush)
}
$.ajax({
type: "POST",
url: path + "/site/savaFinPro",
data: $('#myform').serialize()+ "&add=" + JSON.stringify(addpush),
dataType: "text",
success: function (data) {
if (data == "success") {
alertShow("添加成功", path + "/site/findFinPro");
} else if (data == "err") {
alertShow("添加失败");
}
},
error: function () {
alertShow("服务器忙");
}
});
}
表现层controller
@RequestMapping(value = "/savaFinPro")
@ResponseBody
public String savaFinPro(finPro f, String add) {
try {
int i = IndexService.savaFinPro(f);
if (i > 0) {
Map<String, Object> proSonMap = new HashMap<>();
Map<String, Object> map = new HashMap<>();
List<finPro> finProAll = IndexService.findFinProAll(map);
proSonMap.put("finisproId",finProAll.get(0).getId());
JSONArray json= JSONArray.fromObject(add);
for (int j = 0; j < json.size()-2; j++) {
net.sf.json.JSONObject js= json.getJSONObject(j);
proSonMap.put("ordinal",j+1);
proSonMap.put("content",js.get("content"));
proSonMap.put("amount",js.get("amount"));
proSonMap.put("schedule",js.get("schedule"));
proSonMap.put("remarks",js.get("remarks"));
proSonMap.put("createDate",js.get("createDate"));
Integer k = IndexService.insertProSon(proSonMap);
}
return "success";
} else {
return "err";
}
} catch (Exception e) {
logger.info(e.getMessage(), e);
}
return null;
}
值得说明的是:获取刚插入最新一条数据的id不要去查,我这里有些特殊,先写了,建议:
xml中
将如下代码放入中的开始部分(mybaitis),打个debug,走一步运行完插入sql,回来看一下你的插入的实体类id,就是刚插入的数据的id。
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
具体想了解去查查,这边不多做介绍了,不然跑题了。。。
二、回显并删除代码如下
点击页面内数据的编辑按钮(也就是主表),弹出模态框之前,进行回显,并绑定删除
function del(id) {
// console.info(id);
$.ajax({
type: "POST",
url: path + "/site/deleteProSonByid",
data: {
id:id
},
success: function (data) {
if (data == "success") {
//删除按钮所在的tr对象
trElemnet.parentNode.removeChild(trElemnet);
} else if (data == "err") {
}
}
});
}
function updateDev(id) {
$.ajax({
type: "POST",
url: path + "/site/finProSon",
data: {"finisproId": id},
dataType: "json",
success: function (data) {
delBaby();
for (var i = 0; i < data.length; i++) {
//创建tr元素
var trElemnet = document.createElement("tr");
//创建td元素
var td0Element = document.createElement("td");
td0Element.style.display='none';
var td1Element = document.createElement("td");
var td2Element = document.createElement("td");
var td3Element = document.createElement("td");
var td4Element = document.createElement("td");
var td5Element = document.createElement("td");
var td6Element = document.createElement("td");
var td7Element = document.createElement("td");
//将数据添加到td元素
// td1Element.innerHTML = "";
// console.info(data[i].id);
td0Element.innerHTML = data[i].id;
td1Element.innerHTML = i+1;
td2Element.innerHTML = data[i].content;
td3Element.innerHTML = data[i].amount;
td4Element.innerHTML = data[i].schedule;
td5Element.innerHTML = data[i].createDate;
td6Element.innerHTML = data[i].remarks;
//创建按钮
var delElement = document.createElement("input");
delElement.type = "button";
delElement.value = "删除";
delElement.className = "btn btn-danger btn-sm";
//为按钮添加单击事件
delElement.onclick = function () {
//删除按钮所在的tr对象
var i = this.parentNode.parentNode.rowIndex;
document.getElementById('proSon').deleteRow(i-1);
del(this.parentNode.parentNode.childNodes.valueOf()[0].innerText);
};
td7Element.appendChild(delElement);
//将td元素添加到tr元素中
trElemnet.appendChild(td0Element);
trElemnet.appendChild(td1Element);
trElemnet.appendChild(td2Element);
trElemnet.appendChild(td3Element);
trElemnet.appendChild(td4Element);
trElemnet.appendChild(td5Element);
trElemnet.appendChild(td6Element);
trElemnet.appendChild(td7Element);
//将tr元素添加到tbody元素中
// let products = document.getElementById("products");
// document.getElementById("mytable").insertBefore(trElemnet,products);
document.getElementById("proSon").appendChild(trElemnet);
}
}
});
//完全可以使用一条js来操作,下次改
$("#upDev").show();
$("#addDev").hide();
//点击提交编辑按钮
var add2 = [];
$("#upDev").click(function () {
$("#proSon input:text,input[type=number],input[type=date]").each(
function () {
var val = $(this).val();
add2.push(val);
}
);
// console.info(add2);
var addpush2 = [];
if (add2.length != 0) {
var countInLine = 5;//一行几个数
for (var i = 0; i < add2.length; i++) {
if (i % countInLine == 0) {
var obj = new Object();
obj.content = add2[i];
obj.amount = add2[i + 1];
obj.schedule = add2[i + 2];
obj.createDate = add2[i + 3];
obj.remarks = add2[i + 4];
addpush2.push(obj);
}
}
// console.info(addpush2);
}
$.ajax({
type: "POST",
url: path + "/site/updateFinPro",
data: $('#myform').serialize()+ "&add=" + JSON.stringify(addpush2),
dataType: "text",
success: function (data) {
if (data == "success") {
alertShow("修改成功", path + "/site/findFinPro");
} else if (data == "err") {
alertShow("修改失败");
}
}
});
});
//回显表单数据
$.ajax({
type: "POST",
url: path + "/site/findFinProUpdate",
data: {"id": id},
dataType: "json",
success: function (data) {
for (var i = 0; i < data.length; i++) {
$("#devNum").val(data[i].devNum);
$("#personCharge").val(data[i].personCharge);
$("#createDate").val(data[i].createDate);
$("#chargCurrent").val(data[i].chargCurrent);
$("#personCharge").val(data[i].personCharge);
$("#remarks").val(data[i].remarks);
$("#devType option ").each(function () {
if($(this).val()== data[i].devType ){
$(this).attr("selected","selected");
}
});
$("#customerUnitId option ").each(function () {
if($(this).val()== data[i].customerUnitId ){
$(this).attr("selected","selected");
}
});
}
}
})
}
表现层和增加是一样的,只不过,传入主表id,不需要新建的时候映射会来而已。略过,不懂详看增加的表现层
@RequestMapping(value = "/updateFinPro")
@ResponseBody
public String updateFinPro(finPro fin, String add) {
try {
int i = IndexService.updateFinPro(fin);
if (i > 0) {
Map<String, Object> proSonMap = new HashMap<>();
Map<String, Object> map = new HashMap<>();
proSonMap.put("finisproId",fin.getId());
JSONArray json= JSONArray.fromObject(add);
for (int j = 0; j < json.size()-2; j++) {
net.sf.json.JSONObject js= json.getJSONObject(j);
proSonMap.put("ordinal",j+1);
proSonMap.put("content",js.get("content"));
proSonMap.put("amount",js.get("amount"));
proSonMap.put("schedule",js.get("schedule"));
proSonMap.put("remarks",js.get("remarks"));
proSonMap.put("createDate",js.get("createDate"));
Integer k = IndexService.insertProSon(proSonMap);
}
return "success";
} else {
return "err";
}
} catch (Exception e) {
logger.info(e.getMessage(), e);
}
return null;
}
说明:表现层json.size()-2主要是因为,多携带了不必要数据
基本功能实现了,最佳实践还在摸索,若有同学已经完事,敬请骚扰。
人生如山,为梦而攀。