【发布时间】:2019-09-02 15:56:16
【问题描述】:
我有一个使用 Java 和 Thymeleaf 的 Spring Boot 应用程序。在其中,我有一个带有 JQuery DataTable 的页面。该表中有数千行,因此虽然我目前只是将其全部放在页面上并让 JQuery 完全处理它,但我想切换到使用 ServerSide 处理来进行分页、排序等。
我设置为在后端执行此操作,在那里我可以将开始和结束行号以及动态排序信息传递给我的 SQL 查询。但是,我的问题是,当用户单击“下一页”按钮或排序按钮时,我无法准确弄清楚 DataTables 是如何尝试通过控制器通知我的。 我的控制器在哪里/如何获取此信息,以便我可以将其插入我的 SQL 查询并返回必要的信息?
所以,假设我有一个示例对象,比如“人”。
public class Person {
private static String PERSON_IMAGE = "<img th:src=\"@{/images/personimage.png}\" alt=\"icon\"/>";
private static String PERSON_IMAGE_2 = "<img th:src=\"@{/images/personimage2.png}\" alt=\"icon\"/>";
private String name;
private String socialSecurity;
private String birthdate;
private String gender;
private String personImage;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSocialSecurity() {
return socialSecurity;
}
public void setSocialSecurity(String socialSecurity) {
this.socialSecurity = socialSecurity;
}
public String getBirthdate() {
return birthdate;
}
public void setBirthdate(String birthdate) {
this.birthdate = birthdate;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getPersonImage() {
if(null != birthdate) {
return PERSON_IMAGE;
} else {
return PERSON_IMAGE_2;
}
}
}
所以,在我的 Thymeleaf HTML 页面上,我曾经有以下内容:(版本 1)
<table id="myDataTable" class="dataTable display compact">
<thead>
<tr>
<th>Name</th>
<th>Social Security</th>
<th>Birthdate</th>
<th>Gender</th>
</tr>
</thead>
<tbody>
<tr th:each="person : ${peopleList}">
<td th:attr="data-order=${person.name}"><a th:href="|javascript:openPersonDetail('${person.socialSecurity}');|"><span th:text="${person.name}">name</span></a></td>
<td th:text="${person.socialSecurity}">socialSecurity</td>
<td class="dt-body-center" th:text="${person.birthdate}">birthdate</td>
<td class="dt-body-center" th:text="${person.gender}">gender</td>
</tr>
</tbody>
</table>
我的页面controller很简单,只是传入了一个完整的人员列表,如下:(Version 1)
@GetMapping("/ApplicationName/MyDataTablePage")
public String myDataTablePage(Model model) {
SearchCriteria searchCriteria = new SearchCriteria();
searchCriteria.setOrderByString("name");
searchCriteria.setUsePaging(false);
searchCriteria.setFIRST_NUMBER(null);
searchCriteria.setLAST_NUMBER(null);
model.addAttribute("peopleList", myMapperService.getPeople(searchCriteria)); //returns an ArrayList<Person>
return "/pages/MyDataTablePage";
}
最后,我的 Javascript 曾经有以下内容:(版本 1)
$(document).ready(function() {
$('#myDataTable').DataTable({
"destroy" : true,
"scrollY" : 300,
"scrollCollapse" : true,
"paging" : true,
"autoWidth" : true,
"ordering" : true,
"searching" : false,
"order" : [ [ 0, 'asc' ] ],
"pageLength" : 20,
"lengthChange" : false,
"pagingType" : "full_numbers",
"dom" : '<"top"ip>rt<"bottom"fl><"clear">'
});
});
这可行,但我想切换 DataTable 以使用服务器端处理,因此第一步是(1)更改主页控制器以停止将人员列表附加到模型,(2)创建一个新的控制器,它将我的 ArrayList 作为 JSON 返回给 DataTable 自己调用,(3) 将主页的 html 更改为不再向 DataTable 提供任何 tbody 标记,以及 (4)更改创建表的 javascript 以自行放入数据。
================================================ ===============
这让我想到了以下元素的第 2 版。
我更改后的 Thymeleaf HTML 页面:(第 2 版)
<table id="myDataTable" class="dataTable display compact">
<thead>
<tr>
<th>Name</th>
<th>Social Security</th>
<th>Birthdate</th>
<th>Gender</th>
</tr>
</thead>
</table>
我更改的页面控制器:(版本2)
@GetMapping("/ApplicationName/MyDataTablePage")
public String myDataTablePage(Model model) {
return "/pages/MyDataTablePage";
}
我的新数据表控制器:
@RequestMapping(path = "/ApplicationName/Data/Person", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public List<Person> getPersonData() {
System.out.println("I was called!");
SearchCriteria searchCriteria = new SearchCriteria();
searchCriteria.setOrderByString("name");
searchCriteria.setUsePaging(false);
searchCriteria.setFIRST_NUMBER(null);
searchCriteria.setLAST_NUMBER(null);
return myMapperService.getPeople(searchCriteria); //returns an ArrayList<Person>
}
我更改的(更复杂的)Javascript:(第 2 版)
$(document).ready(function () {
$('#myDataTable').DataTable({
'destroy' : true,
'serverSide' : true,
'sAjaxSource': '/ApplicationName/Data/Person',
'sAjaxDataProp': '',
'order': [ [ 0, 'asc' ] ],
'columns':
[
{ 'data': 'name',
'render': function(data, type, row, meta){
if(type === 'display'){
data = '<a href="javascript:openPersonDetail(''+ row.socialSecurity +'');">' + data + '</a>'
}
return data;
}
} ,
{ 'data': 'socialSecurity'} ,
{ 'data': 'birthdate'} ,
{ 'data': 'gender'}
],
'scrollY' : 300,
'scrollCollapse' : true,
'paging' : true,
'autoWidth' : true,
'ordering' : true,
'searching' : false,
'pageLength' : 20,
'lengthChange' : false,
'pagingType' : 'full_numbers',
'dom' : '<"top"ip>rt<"bottom"fl><"clear">'
});
});
================================================ ===============
这也有效。特别是如果我删除“'serverSide':true”配置 - DataTable 的工作方式与我进行上述更改之前完全一样,但现在它调用我的新 Data JSON 控制器而不是使用模型属性。
问题:
但是,将“'serverSide' : true”配置添加到 DataTable 时,每次我转到表的新“页面”时,它都会调用我的“/Clinic/Detail/Data/Patient”控制器每一次。
但是,我需要 DataTables 来传递有关用户选择的页面或用户尝试排序的列的控制器信息。我还需要(动态地)传递表格的总行数(计数),以便 DataTables 可以为用户正确设置页码。
DataTables 是否向我的控制器发送了一些我可以获取的附加参数? @PathVariable("whatever") 之类的东西?
我觉得我离让这项工作如此接近,但我被困在这一点上。
非常感谢任何帮助!
【问题讨论】:
-
当您指定
serverside: true时,draw请求中会包含其他参数,请参阅docs。如果您查看浏览器工具的网络面板,您将能够在数据表加载时看到这一点。这些参数是您的控制器需要使用的。 -
@markpsmith 感谢您的评论。是的,我现在正按计划进行这项工作,尽管无论出于何种原因,我的应用程序似乎都想要使用这些变量的旧(我认为)版本,即使我正在为数据表
<version>1.10.19</version>拉入 webjars。无论如何,一旦我让它完全工作,我计划发布我自己问题的答案。假设一切顺利... -
@markpsmith 既然您似乎知道您在说什么,也许您可以帮我解决另一个问题?我一直在浏览有关 DataTables 的文档,但找不到它。有没有办法将自定义排序参数字符串添加到列列表中,类似于以下示例.... 'columns': [ { 'data' : 'name', 'customSortableParamer' : 'FIRST_NAME' }, { 'data' : 'gender' } ],并在用户排序的请求参数中将该值返回给我?
-
您能补充一下您使用的DataTable、Spring-Boot、Java、Thymeleaf等版本吗?
标签: java jquery spring-boot datatables thymeleaf