我正在尝试创建基本 datatables.net 和 coldfusion 服务器端示例,但它似乎不起作用
I am trying to create basic datatables.net and coldfusion server side example but it doesnt seem to works
此示例基于此 link
https://datatables.net/forums/discussion/40613/datatable-jquery-server-side-with-adobe-cold-fusion-and-sql-server
我正在使用数据表版本 1.10
在第一页加载时,所有数据已成功加载到#formsTable
但是点击排序搜索分页就不行了
它只是挂在 'processing..'
pageA.cfm(这里只显示脚本部分...)
<script type="text/javascript">
$(document).ready(function(){
$('#formsTable').DataTable({
processing:true,
serverSide:true,
ajax:{
url:'pageB.cfm'
},
columns:[
{title: "id",data:'id'},
{title: "Name",data:'name'},
{title: "Emp.No",data:'empno'},
{title: "IC",data:'ic'}
]
})
})
</script>
pageB.cfm(服务器端)
<cfcontent reset="true">
<cfset listColumns = "id,emp_no,emp_name,number_id2" />
<cfset sIndexColumn = "id" />
<cfparam name="draw" default="1" type="integer" />
<cfparam name="start" default="0" type="integer" />
<cfparam name="length" default="10" type="integer" />
<cfparam name="url.sSearch" default="" type="string" />
<cfparam name="url.iSortingCols" default="0" type="integer" />
<!--- query data --->
<cfquery datasource="hrms" name="qFiltered">
select id,emp_no,emp_name,number_id2 from employee
<cfif len(trim(url.sSearch))>
Where
(
<cfloop list="#listColumns#" index="thisColumn">
<cfif thisColumn neq listFirst(listColumns)>
OR
</cfif>
#thisColumn# LIKE <cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="%#trim(url.sSearch)#%" />
</cfloop>
)
</cfif>
<cfif url.iSortingCols gt 0>
ORDER BY
<cfloop from="0" to="#url.iSortingCols-1#" index="thisS">
<cfif thisS is not 0>, </cfif>
#listGetAt(listColumns,(url["iSortCol_"&thisS]+1))#
<cfif listFindNoCase("asc,desc",url["sSortDir_"&thisS]) gt 0>
#url["sSortDir_"&thisS]#
</cfif>
</cfloop>
</cfif>
</cfquery>
<!--- query data count --->
<cfquery dbtype="query" name="qCount">
SELECT COUNT(#sIndexColumn#) as total
FROM qFiltered
</cfquery>
<!--- Output --->
{"draw": <cfoutput>#val(draw)#</cfoutput>,
"recordsTotal": <cfoutput>#qCount.total#</cfoutput>,
"recordsFiltered": <cfoutput>#qFiltered.recordCount#</cfoutput>,
"aaData": [
<cfoutput query="qFiltered" startrow="#val(start+1)#" maxrows="#val(length)#">
<cfif currentRow gt (start+1)>,</cfif>
{
"id":#SerializeJSON(qFiltered.currentrow)#,
"name":#SerializeJSON(qFiltered.emp_name)#,
"empno":#SerializeJSON(qFiltered.emp_no)#,
"ic":
<cfif trim(qFiltered.number_id2) neq '[empty string]'>
#SerializeJSON(qFiltered.number_id2)#
<cfelse>
""
</cfif>
}
</cfoutput> ] }
我卡在这里了,pageB.cfm 上好像少了什么?
已编辑:
感谢@user12031119 指出从 pageA.cfm 发送到 pageB.cfm 的参数现在与 v1.10 不同,所以基本上这些参数应该改变 :-
sEcho : 绘制
iDisplayStart : 开始
iDisplayLength:长度
iTotalRecords:记录总数
iTotalDisplayRecords : 记录过滤
通过该更改,我现在可以单击 next/prev 页面(分页),但搜索和排序仍然不起作用
是的,很遗憾,您在 datatables.net 上查看的代码示例是针对遗留数据表的。在数据表 1.10.x 下,您将必须使用 1.10 版在您的 returned json 结构中期望的升级密钥。看起来您已经使用新参数更新了 pageA.cfm,但是您还需要在 pageB.cfm.
中更新服务器端 return 参数
这是升级到 1.10 版的指南https://datatables.net/upgrade/1.10
这是服务器端 1.10 的新参数指南 https://datatables.net/manual/server-side
编辑 1 感谢 James A Mohler
我自己注意到的每个问题编辑 2
显然我错了,当从服务器 returned 时,datatables 只接受一个数组数组。显然它也接受一个结构数组,这有助于简化我的回答。但是,这将需要为 select 语句中的列设置别名以匹配 pageA.cfm 中定义的列定义。话虽如此,这是需要进行的更改。
对 pageB.cfm 的第一个代码修改是为 select 状态表中的列设置别名,以匹配它们在 pageA.cfm 中的定义。
<cfquery datasource="hrms" name="qFiltered">
select id as id, emp_no as empno, emp_name as name, number_id2 as ic from employee
完成后,将 <cfoutput>
块中的以下内容从 pageB.cfm
更改为
- 将
sEcho
更改为draw
- 将
iTotalRecords
更改为recordsTotal
- 将
iTotalDisplayRecords
更改为recordsFiltered
- 将
aaData
更改为data
- 使用
serializeJson()
和 "struct" 选项来 return 结构数组,其键值与您在 pageA.cfm 中定义的方式相匹配。如果您使用的是 ACF 而不是 lucee,那么您可能必须将 pageA.cfm 中的列定义更改为大写,因为 ACF 不保留大小写和大写的键名称。
<!--- Output --->
<cfoutput>
{
"draw": #val(url.sEcho)#,
"recordsTotal": #qCount.total#,
"recordsFiltered": #qFiltered.recordCount#,
"data": #serializeJson(qFiltered, "struct")#
}
</cfoutput>
好的,现在终于可以用了。
就是这样,基本的 datatables.net coldfusion/lucee 服务器端示例。
数据表版本 1。10.xx
语言Coldfusion/lucee
pageA.cfm(脚本)
<script type="text/javascript">
$(document).ready(function(){
$('#formsTable').DataTable({
processing:true,
serverSide:true,
ajax:{
url:'pageB.cfm',
type :'post'
},
columns:[
{title: "id",data:'id'},
{title: "Name",data:'name'},
{title: "Emp.No",data:'empno'},
{title: "IC",data:'ic'}
],
language: {
infoEmpty: "No records available",
}
})
})
</script>
pageB.cfm
<cfcontent reset="true">
<cfset listColumns = "id,emp_no,emp_name,number_id2" />
<cfset sIndexColumn = "id" />
<cfparam name="draw" default="1" type="integer" />
<cfparam name="start" default="0" type="integer" />
<cfparam name="length" default="10" type="integer" />
<cfparam name="search" default="" type="string" />
<cfif len(form["search[value]"]) gt 0>
<cfset search=form["search[value]"]>
</cfif>
<!--- Data set after filtering --->
<cfquery datasource="hrms" name="qFiltered">
select id,emp_no,emp_name,number_id2 from employee
<cfif len(trim(search))>
where
(
<cfloop list="#listColumns#" index="thisColumn">
<cfif thisColumn neq listFirst(listColumns)>
OR
</cfif>
#thisColumn# LIKE <cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="%#trim(search)#%" />
</cfloop>
)
</cfif>
<cfif form["order[0][column]"] gt 0>
ORDER BY
<cfif form["order[0][column]"] eq '1'>
emp_name <cfif form["order[0][dir]"] eq 'desc'>desc</cfif>
</cfif>
<cfif form["order[0][column]"] eq '2'>
emp_no <cfif form["order[0][dir]"] eq 'desc'>desc</cfif>
</cfif>
<cfif form["order[0][column]"] eq '3'>
number_id2 <cfif form["order[0][dir]"] eq 'desc'>desc</cfif>
</cfif>
</cfif>
</cfquery>
<!--- Total data set length --->
<cfquery dbtype="query" name="qCount">
SELECT COUNT(#sIndexColumn#) as total
FROM qFiltered
</cfquery>
<cfif qFiltered.recordcount gt 0>
<cfset recordsTotal=#qCount.total#>
<cfelse>
<cfset recordsTotal=0>
</cfif>
<!---
Output
--->
{"draw": <cfoutput>#val(draw)#</cfoutput>,
"recordsTotal": <cfoutput>#recordsTotal#</cfoutput>,
"recordsFiltered": <cfoutput>#qFiltered.recordCount#</cfoutput>,
"data":
<cfif qFiltered.recordcount gt 0>
[
<cfoutput query="qFiltered" startrow="#val(start+1)#" maxrows="#val(length)#">
<cfif currentRow gt (start+1)>,</cfif>
{
"id":#SerializeJSON(qFiltered.currentrow)#,
"name":#SerializeJSON(qFiltered.emp_name)#,
"empno":#SerializeJSON(qFiltered.emp_no)#,
"ic":
<cfif trim(qFiltered.number_id2) neq '[empty string]'>
#SerializeJSON(qFiltered.number_id2)#
<cfelse>
""
</cfif>
}
</cfoutput> ]
<cfelse>
""
</cfif>
}
首先,检查您的 JSON 输出是否有效 (jsonlint.com)
然后,将您的 JSON 输出包装到 cfsavecontent:
<cfsavecontent variable="json">
<cfoutput>
your output here
</cfoutput>
</cfsavecontent>
然后使用此代码 return JSON:
<cfset lastModDate = DateFormat(Now(),'ddd, dd mmm YYYY') & ' ' & TimeFormat(DateConvert('local2Utc', Now()), 'HH:mm:ss') & ' GMT'>
<cfheader name="Expires" value="#DateAdd('m', -1, Now())#">
<cfheader name="Last-Modified" value="#lastModDate#">
<cfheader name="cache-control" value="must-revalidate">
<cfheader name="Pragma" value="no-cache">
<cfcontent type="text/x-json" />
<cfoutput>#json#</cfoutput>
此示例基于此 link
https://datatables.net/forums/discussion/40613/datatable-jquery-server-side-with-adobe-cold-fusion-and-sql-server
我正在使用数据表版本 1.10
在第一页加载时,所有数据已成功加载到#formsTable
但是点击排序搜索分页就不行了
它只是挂在 'processing..'
pageA.cfm(这里只显示脚本部分...)
<script type="text/javascript">
$(document).ready(function(){
$('#formsTable').DataTable({
processing:true,
serverSide:true,
ajax:{
url:'pageB.cfm'
},
columns:[
{title: "id",data:'id'},
{title: "Name",data:'name'},
{title: "Emp.No",data:'empno'},
{title: "IC",data:'ic'}
]
})
})
</script>
pageB.cfm(服务器端)
<cfcontent reset="true">
<cfset listColumns = "id,emp_no,emp_name,number_id2" />
<cfset sIndexColumn = "id" />
<cfparam name="draw" default="1" type="integer" />
<cfparam name="start" default="0" type="integer" />
<cfparam name="length" default="10" type="integer" />
<cfparam name="url.sSearch" default="" type="string" />
<cfparam name="url.iSortingCols" default="0" type="integer" />
<!--- query data --->
<cfquery datasource="hrms" name="qFiltered">
select id,emp_no,emp_name,number_id2 from employee
<cfif len(trim(url.sSearch))>
Where
(
<cfloop list="#listColumns#" index="thisColumn">
<cfif thisColumn neq listFirst(listColumns)>
OR
</cfif>
#thisColumn# LIKE <cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="%#trim(url.sSearch)#%" />
</cfloop>
)
</cfif>
<cfif url.iSortingCols gt 0>
ORDER BY
<cfloop from="0" to="#url.iSortingCols-1#" index="thisS">
<cfif thisS is not 0>, </cfif>
#listGetAt(listColumns,(url["iSortCol_"&thisS]+1))#
<cfif listFindNoCase("asc,desc",url["sSortDir_"&thisS]) gt 0>
#url["sSortDir_"&thisS]#
</cfif>
</cfloop>
</cfif>
</cfquery>
<!--- query data count --->
<cfquery dbtype="query" name="qCount">
SELECT COUNT(#sIndexColumn#) as total
FROM qFiltered
</cfquery>
<!--- Output --->
{"draw": <cfoutput>#val(draw)#</cfoutput>,
"recordsTotal": <cfoutput>#qCount.total#</cfoutput>,
"recordsFiltered": <cfoutput>#qFiltered.recordCount#</cfoutput>,
"aaData": [
<cfoutput query="qFiltered" startrow="#val(start+1)#" maxrows="#val(length)#">
<cfif currentRow gt (start+1)>,</cfif>
{
"id":#SerializeJSON(qFiltered.currentrow)#,
"name":#SerializeJSON(qFiltered.emp_name)#,
"empno":#SerializeJSON(qFiltered.emp_no)#,
"ic":
<cfif trim(qFiltered.number_id2) neq '[empty string]'>
#SerializeJSON(qFiltered.number_id2)#
<cfelse>
""
</cfif>
}
</cfoutput> ] }
我卡在这里了,pageB.cfm 上好像少了什么?
已编辑: 感谢@user12031119 指出从 pageA.cfm 发送到 pageB.cfm 的参数现在与 v1.10 不同,所以基本上这些参数应该改变 :-
sEcho : 绘制
iDisplayStart : 开始
iDisplayLength:长度
iTotalRecords:记录总数
iTotalDisplayRecords : 记录过滤
通过该更改,我现在可以单击 next/prev 页面(分页),但搜索和排序仍然不起作用
是的,很遗憾,您在 datatables.net 上查看的代码示例是针对遗留数据表的。在数据表 1.10.x 下,您将必须使用 1.10 版在您的 returned json 结构中期望的升级密钥。看起来您已经使用新参数更新了 pageA.cfm,但是您还需要在 pageB.cfm.
中更新服务器端 return 参数这是升级到 1.10 版的指南https://datatables.net/upgrade/1.10
这是服务器端 1.10 的新参数指南 https://datatables.net/manual/server-side
编辑 1 感谢 James A Mohler
我自己注意到的每个问题编辑 2
显然我错了,当从服务器 returned 时,datatables 只接受一个数组数组。显然它也接受一个结构数组,这有助于简化我的回答。但是,这将需要为 select 语句中的列设置别名以匹配 pageA.cfm 中定义的列定义。话虽如此,这是需要进行的更改。
对 pageB.cfm 的第一个代码修改是为 select 状态表中的列设置别名,以匹配它们在 pageA.cfm 中的定义。
<cfquery datasource="hrms" name="qFiltered">
select id as id, emp_no as empno, emp_name as name, number_id2 as ic from employee
完成后,将 <cfoutput>
块中的以下内容从 pageB.cfm
- 将
sEcho
更改为draw
- 将
iTotalRecords
更改为recordsTotal
- 将
iTotalDisplayRecords
更改为recordsFiltered
- 将
aaData
更改为data
- 使用
serializeJson()
和 "struct" 选项来 return 结构数组,其键值与您在 pageA.cfm 中定义的方式相匹配。如果您使用的是 ACF 而不是 lucee,那么您可能必须将 pageA.cfm 中的列定义更改为大写,因为 ACF 不保留大小写和大写的键名称。
<!--- Output --->
<cfoutput>
{
"draw": #val(url.sEcho)#,
"recordsTotal": #qCount.total#,
"recordsFiltered": #qFiltered.recordCount#,
"data": #serializeJson(qFiltered, "struct")#
}
</cfoutput>
好的,现在终于可以用了。
就是这样,基本的 datatables.net coldfusion/lucee 服务器端示例。
数据表版本 1。10.xx
语言Coldfusion/lucee
pageA.cfm(脚本)
<script type="text/javascript">
$(document).ready(function(){
$('#formsTable').DataTable({
processing:true,
serverSide:true,
ajax:{
url:'pageB.cfm',
type :'post'
},
columns:[
{title: "id",data:'id'},
{title: "Name",data:'name'},
{title: "Emp.No",data:'empno'},
{title: "IC",data:'ic'}
],
language: {
infoEmpty: "No records available",
}
})
})
</script>
pageB.cfm
<cfcontent reset="true">
<cfset listColumns = "id,emp_no,emp_name,number_id2" />
<cfset sIndexColumn = "id" />
<cfparam name="draw" default="1" type="integer" />
<cfparam name="start" default="0" type="integer" />
<cfparam name="length" default="10" type="integer" />
<cfparam name="search" default="" type="string" />
<cfif len(form["search[value]"]) gt 0>
<cfset search=form["search[value]"]>
</cfif>
<!--- Data set after filtering --->
<cfquery datasource="hrms" name="qFiltered">
select id,emp_no,emp_name,number_id2 from employee
<cfif len(trim(search))>
where
(
<cfloop list="#listColumns#" index="thisColumn">
<cfif thisColumn neq listFirst(listColumns)>
OR
</cfif>
#thisColumn# LIKE <cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="%#trim(search)#%" />
</cfloop>
)
</cfif>
<cfif form["order[0][column]"] gt 0>
ORDER BY
<cfif form["order[0][column]"] eq '1'>
emp_name <cfif form["order[0][dir]"] eq 'desc'>desc</cfif>
</cfif>
<cfif form["order[0][column]"] eq '2'>
emp_no <cfif form["order[0][dir]"] eq 'desc'>desc</cfif>
</cfif>
<cfif form["order[0][column]"] eq '3'>
number_id2 <cfif form["order[0][dir]"] eq 'desc'>desc</cfif>
</cfif>
</cfif>
</cfquery>
<!--- Total data set length --->
<cfquery dbtype="query" name="qCount">
SELECT COUNT(#sIndexColumn#) as total
FROM qFiltered
</cfquery>
<cfif qFiltered.recordcount gt 0>
<cfset recordsTotal=#qCount.total#>
<cfelse>
<cfset recordsTotal=0>
</cfif>
<!---
Output
--->
{"draw": <cfoutput>#val(draw)#</cfoutput>,
"recordsTotal": <cfoutput>#recordsTotal#</cfoutput>,
"recordsFiltered": <cfoutput>#qFiltered.recordCount#</cfoutput>,
"data":
<cfif qFiltered.recordcount gt 0>
[
<cfoutput query="qFiltered" startrow="#val(start+1)#" maxrows="#val(length)#">
<cfif currentRow gt (start+1)>,</cfif>
{
"id":#SerializeJSON(qFiltered.currentrow)#,
"name":#SerializeJSON(qFiltered.emp_name)#,
"empno":#SerializeJSON(qFiltered.emp_no)#,
"ic":
<cfif trim(qFiltered.number_id2) neq '[empty string]'>
#SerializeJSON(qFiltered.number_id2)#
<cfelse>
""
</cfif>
}
</cfoutput> ]
<cfelse>
""
</cfif>
}
首先,检查您的 JSON 输出是否有效 (jsonlint.com) 然后,将您的 JSON 输出包装到 cfsavecontent:
<cfsavecontent variable="json">
<cfoutput>
your output here
</cfoutput>
</cfsavecontent>
然后使用此代码 return JSON:
<cfset lastModDate = DateFormat(Now(),'ddd, dd mmm YYYY') & ' ' & TimeFormat(DateConvert('local2Utc', Now()), 'HH:mm:ss') & ' GMT'>
<cfheader name="Expires" value="#DateAdd('m', -1, Now())#">
<cfheader name="Last-Modified" value="#lastModDate#">
<cfheader name="cache-control" value="must-revalidate">
<cfheader name="Pragma" value="no-cache">
<cfcontent type="text/x-json" />
<cfoutput>#json#</cfoutput>