Thymeleaf的List各类问题(后端接收对象集合)
需求是前端页面循环展示一个后端来的数据,并且前端循环的列表每个都有点击事件,需要把列表中的自己的id传入到触发事件中,最后提交的时候把循环列表的对象集合数据全部提交到后端。我使用的是SpringBoot+Thymeleaf,下面用代码一步步展示过程。
最近在Thymeleaf做一个页面的时候,因为需要使用List循环展示,提交List到后端,出现各种问题,解决起来也不甚痛苦,这里把解决问题的方式分享一下,也便于自己记录。
介绍:
需求是前端页面循环展示一个后端来的数据,并且前端循环的列表每个都有点击事件,需要把列表中的自己的id传入到触发事件中,最后提交的时候把循环列表的数据全部提交到后端。
我使用的是SpringBoot+Thymeleaf,下面用代码一步步展示过程
1.开始的页面,简单的展示(无循环)
前端:
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('申请预约(未预约)列表')" />
<th:block th:include="include :: datetimepicker-css" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-schapplication-add">
<div class="form-group">
<label class="col-sm-3 control-label">申请时间:</label>
<div class="col-sm-8">
<div class="input-group date">
<input name="appTime" th:value="${#dates.format(schInsTime, 'yyyy-MM-dd hh:mm')}" id="appTime" class="form-control" placeholder="yyyy-MM-dd" type="text" th:data-insItemId="${insItemId}">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: datetimepicker-js" />
<script th:inline="javascript">
var prefix = ctx + "schmanage/schapplication"
$("#form-schapplication-add").validate({
focusCleanup: true
});
$("input[name='appTime']").datetimepicker({
// format: "yyyy-mm-dd",
language: "ja",
format: "yyyy-mm-dd HH:ii",
// minView: "month",
minView: 0,
autoclose: true,
minuteStep:10
}).on('changeDate',function(event){
console.log(event.date);
// $.operate.post(prefix+"/activeInsTime",{'insActiveTime':event.date});
});
</script>
</body>
</html>
后端:
@RequestMapping( "/getSchInsTimeByItemsId")
public String getSchInsTimeByItemsId(String insItemsId,ModelMap mmap){
mmap.put("schInsTime", scheduledApplicationService.getSchInsTimeByItemsId(insItemsId));
mmap.put("insItemId", insItemsId);
return prefix + "/schInsTime";
}
上面是一个简单的跳转页面,展示ModelMap 里的数据的无循环的。url访问xxx/getSchInsTimeByItemsId?insItemsId=xxx 即可跳转到前端页面,如下图
2.接着需求 需要改成循环列表展示,并且实现可以点击循环的列表,并将其中的id传入触发事件,(贴上前端代码和后端的Controller和实体类代码)
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('申请预约(未预约)列表')" />
<th:block th:include="include :: datetimepicker-css" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-schapplication-add" action="/schmanage/schapplication/test" >
<div class="form-group" id="schAppLication" th:each="schAppInsItem,schAppInsItemStat:${schAppInsVOs}">
<label class="col-sm-3 control-label"><span th:text="${schAppInsItem.insItemsName}"> </span></label>
<div class="col-sm-8">
<div class="input-group date">
<!--这里要把循环的id取到传入触发事件中,需要写上this.getAttribute(xxx),并且要写th:data-xxx -->
<input th:name="applicationTime" th:value="${#dates.format(schAppInsItem.applicationTime, 'yyyy-MM-dd HH:mm')}" id="appTime" class="form-control" placeholder="yyyy-MM-dd" type="text" th:data-insItemsId="${schAppInsItem.insItemsId}" th:onchange="|changeAppTime(value,this.getAttribute('data-insItemsId'),${schAppInsItemStat.index})|">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: datetimepicker-js" />
<script th:inline="javascript">
var prefix = ctx + "schmanage/schapplication"
$("#form-schapplication-add").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/add", $('#form-schapplication-add').serialize());
}
}
$("input[name='applicationTime']").datetimepicker({
// format: "yyyy-mm-dd",
language: "ja",
format: "yyyy-mm-dd hh:ii",
// minView: "month",
minView: 0,
autoclose: true,
minuteStep:10
})
//触发改变事件
function changeAppTime(appTime,insItemId,index){
console.log(appTime)
$.operate.post(prefix+"/activeInsTime",{'insItemsId':insItemId,'insActiveTime':appTime},activeInsTime);
}
//callback方法,
function activeInsTime(result) {
console.log(result);
if(result.code == web_status.WARNING){
$("input[data-insItemsId="+result.data.insItemsId+"]").val(result.data.applicationTime);
}
}
</script>
</body>
</html>
@RequestMapping( "/schInsTimeToView")
public String schInsTimeToView(@RequestParam List<String> insItemsIds,ModelMap mmap){
mmap.put("schAppInsVOs",scheduledApplicationService.schInsTimeToView(insItemsIds));
return prefix + "/schInsTime";
}
@RequestMapping( "/activeInsTime")
@ResponseBody
public AjaxResult activeInsTime(String insItemsId,Date insActiveTime) throws Exception{
Date resultActiveTime = scheduledApplicationService.activeInsTime(insItemsId, insActiveTime);
if(resultActiveTime == null){
return AjaxResult.success("该时间可以预约");
}else{
SchApplicationVO schApplicationVO = new SchApplicationVO();
schApplicationVO.setApplicationTime(resultActiveTime);
schApplicationVO.setInsItemsId(insItemsId);
return AjaxResult.warn("该时间已被预约/不在上班时间,已为您调整至最近可预约时间",schApplicationVO);
}
}
//省略get,set
public class SchApplicationVO implements Serializable {
/** 检查项目编码 */
private String insItemsId;
/** 检查项目名称 */
private String insItemsName;
private Date applicationTime;
}
动图有点不太会弄,凑合看看吧,目前实现了循环展示列表和改变列表中的任意一个都可以把他的id传参
3.最后需求需要改成 需要把选好的循环列表数据提交后端
这里需求后端接收对象集合,这里坑坑了我挺久,先总结下,首先后端需要把 想跟前端交互的对象装成一个List再封装到一个新的类中,前端需要改th:field进行绑定(当然也需要先用th:object解析),最后的最后,因为我这边是时间格式的,从后端过来的格式还需要处理下,具体看代码,在代码中我添加注释加以说明,最后的效果是前端点击提交,后端接收获取得到List数据
后端代码 (Controller):
/**
* 获取当前预约的能预约到的预约时间
* @param insItemsIds 检查项目id集合
* @return
*/
@RequestMapping( "/schInsTimeToView")
public String schInsTimeToView(@RequestParam List<String> insItemsIds,ModelMap mmap){
SchApplicationOutWap schApplicationOutWap = new SchApplicationOutWap();
schApplicationOutWap.setList(scheduledApplicationService.schInsTimeToView(insItemsIds));
mmap.put("schAppInsVOs",schApplicationOutWap);
return prefix + "/schInsTime";
}
/**
* 医生主动设置预约时间来预约
* @param insItemsId 检查项目id
* @param insActiveTime 主动申请预约时间
*/
@RequestMapping( "/activeInsTime")
@ResponseBody
public AjaxResult activeInsTime(String insItemsId,Date insActiveTime) throws Exception{
Date resultActiveTime = scheduledApplicationService.activeInsTime(insItemsId, insActiveTime);
if(resultActiveTime == null){
return AjaxResult.success("该时间可以预约");
}else{
SchApplicationVO schApplicationVO = new SchApplicationVO();
schApplicationVO.setApplicationTime(resultActiveTime);
schApplicationVO.setInsItemsId(insItemsId);
return AjaxResult.warn("该时间已被预约/不在上班时间,已为您调整至最近可预约时间",schApplicationVO);
}
}
/**
* 确定预约 。前端点提交进入此方法。
*/
@RequestMapping( "/test")
@ResponseBody
public AjaxResult test(SchApplicationOutWap list)
{
System.out.println(list.getList());
return AjaxResult.success();
}
这里我们可以看到 schInsTimeToView方法里面我改动了些,增加了SchApplicationOutWap 这个类里面一个外包裹,其实里面就是只有个List的SchApplicationVO的属性
Pojo
public class SchApplicationOutWap implements Serializable {
private List<SchApplicationVO> list;
//省略get set
}
//省略get,set
public class SchApplicationVO implements Serializable {
/** 检查项目编码 */
private String insItemsId;
/** 检查项目名称 */
private String insItemsName;
// 加上这个可以让前端以此格式输出time
@JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone="GMT+8")
private Date applicationTime;
}
后端想要接收SchApplicationVO对象集合,就必须在其外面再写个对象,像上面这样,才可以跟前端进行绑定(这里本人觉得...一言难尽的设计)
最后附上前端代码:
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('申请预约(未预约)列表')" />
<th:block th:include="include :: datetimepicker-css" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<!-- 这里需要使用 th:object 把刚后端传来的对象解析出来-->
<form class="form-horizontal m" id="form-schapplication-add" th:object="${schAppInsVOs}">
<div class="form-group" id="schAppLication" th:each="schAppInsItem,schAppInsItemStat:${schAppInsVOs.list}">
<label class="col-sm-3 control-label"><span th:text="${schAppInsItem.insItemsName}"> </span></label>
<div class="col-sm-8">
<div class="input-group date" name="appInsItemDiv">
<!-- th:field 进行跟后端绑定, list对应的是后端SchApplicationOutWap 写的List<对象> 的属性名
.applicationTime 是这一行的数据是跟 后端对象里的applicationTime进行绑定,至此,此行不需要写name,因为name=xxx就是applicationTime,不需要写value=xxx,写了也没用,因为绑定了,不信你试试 -->
<input th:field="*{list[__${schAppInsItemStat.index}__].applicationTime}" th:value="${#dates.format(schAppInsItem.applicationTime, 'yyyy-MM-dd HH:mm')}" name="appTime" id="appTime" class="form-control" placeholder="yyyy-MM-dd" type="text" th:data-insItemsId="${schAppInsItem.insItemsId}" th:onchange="|changeAppTime(value,this.getAttribute('data-insItemsId'),${schAppInsItemStat.index})|">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
<input type="hidden" th:field="*{list[__${schAppInsItemStat.index}__].insItemsId}" th:value="${schAppInsItem.insItemsId}">
</div>
</div>
</div>
</form>
<button onclick="submitHandler()" >提交</button>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: datetimepicker-js" />
<script th:inline="javascript">
var prefix = ctx + "schmanage/schapplication"
$("#form-schapplication-add").validate({
focusCleanup: true
});
function submitHandler() {
console.log($('#form-schapplication-add').serialize());
if ($.validate.form()) {
$.operate.post(prefix + "/test", $('#form-schapplication-add').serialize());
}
}
var a = [[${schAppInsVOs}]];
console.log(a.list.length);
//循环绑定事件,这里其实我也研究了挺久,不知道怎么给列表的每个绑定事件,最后只能用这个办法,如果有其他更好的方法,请不吝赐教
for(var i=0;i<a.list.length;i++){
$("input[name='list["+i+"].applicationTime']").val(a.list[i].applicationTime);
$("input[name='list["+i+"].applicationTime'] " ).datetimepicker({
// $("#appTime").datetimepicker({
// format: "yyyy-mm-dd",
language: "zh-CN",
format: "yyyy-mm-dd hh:ii",
// minView: "month",
minView: 0,
autoclose: true,
minuteStep:10
})
}
function activeInsTime(result) {
console.log(result);
if(result.code == web_status.WARNING){
$("input[data-insItemsId="+result.data.insItemsId+"]").val(result.data.applicationTime);
}
}
function changeAppTime(appTime,insItemId,index){
console.log(insItemId);
console.log(appTime);
console.log(index);
$.operate.post(prefix+"/activeInsTime",{'insItemsId':insItemId,'insActiveTime':appTime},activeInsTime);
}
</script>
</body>
</html>
更多推荐
所有评论(0)