I need the help of an expert on this site. I am attempting to bind some JSON data that is return from an AJAX call to my asp page through the method below. The server successfully returns the following data:
{"Records": [ {"LastName":"Harold","FirstName":"Kelly","Floor":"","Office":""}, {"LastName":"Kelly","FirstName":"Jason","Floor":"12","Office":"D01"} ]}
It appears however, that the data does not get binded to the grid and hence the JQXGrid is empty
I don't understand what I am doing wrong. Theoretically everything should working. Maybe I am missing something here.
compile_data.asp:
<%
'Function to convert an ADO recordset into a JSON object
'
'Written by Tracy Dryden, Commonwealth Technology Group, Inc.
'
'Released to the public domain.
function RStoJSON(rs)
dim sFld
dim sFlds
dim sRec
dim sRecs
dim sRecordSet
dim lRecCnt
sRecordSet = ""
sRecs = ""
lRecCnt = 0
if rs.EOF or rs.BOF then
RStoJSON = "null"
else
do while not rs.EOF and not rs.BOF
lRecCnt = lRecCnt + 1
sFlds = ""
for each fld in rs.Fields
sFld = """" & fld.Name & """:""" & toUnicode(fld.Value&"") & """"
sFlds = sFlds & iif(sFlds <> "", ",", "") & sFld
next 'fld
sRec = "{" & sFlds & "}"
sRecs = sRecs & iif(sRecs <> "", "," & vbCrLf, "") & sRec
rs.MoveNext
loop
sRecordSet = "{""Records"": [" & vbCrLf & sRecs & vbCrLf & "]}"
RStoJSON = sRecordSet
end if
end function
function toUnicode(str)
dim x
dim uStr
dim uChr
dim uChrCode
uStr = ""
for x = 1 to len(str)
uChr = mid(str,x,1)
uChrCode = asc(uChr)
if uChrCode = 8 then ' backspace
uChr = "\b"
elseif uChrCode = 9 then ' tab
uChr = "\t"
elseif uChrCode = 10 then ' line feed
uChr = "\n"
elseif uChrCode = 12 then ' formfeed
uChr = "\f"
elseif uChrCode = 13 then ' carriage return
uChr = "\r"
elseif uChrCode = 34 then ' quote
uChr = "\"""
elseif uChrCode = 39 then ' apostrophe
uChr = "\'"
elseif uChrCode = 92 then ' backslash
uChr = "\\"
elseif uChrCode < 32 or uChrCode > 127 then ' non-ascii characters
uChr = "\u" & right("0000" & CStr(uChrCode),4)
end if
uStr = uStr & uChr
next
toUnicode = uStr
end function
function iif(cond,tv,fv)
if cond then
iif = tv
else
iif = fv
end if
end function
%>
<%
Dim cn
Dim rs
Dim sSQL
set cn = Server.CreateObject("ADODB.Connection")
cn.Open "Provider=sqloledb;Data Source=sql8002.site4now.net;Initial Catalog=db_a8d1d3_accmgr; User Id=db_a8d1d3_accmgr_admin;Password=accmgr01;"
sSQL = "SELECT * FROM tbl_offices"
set rs = cn.Execute(sSQL)
response.write(RStoJSON(rs))
'response.write(Request.QueryString("first"))
response.flush
rs.Close
set rs = nothing
cn.close
set cn = nothing
%>
Code in question:
<script type="text/javascript">
var data = ""
$(document).ready(function () {
$.ajax({
type: 'GET',
url: "compile_data.asp",
success:function(response){
data = response
alert(data)
}
});
var source = {
datatype: "json",
datafields: [
{ name: 'LastName', type: 'string' },
{ name: 'FirstName', type: 'string' },
{ name: 'Floor', type: 'string' },
{ name: 'Office', type: 'string' }
],
localdata: data
};
var dataAdapter = new $.jqx.dataAdapter(source);
$("#grid").jqxGrid({
width: getWidth('Grid'),
source: dataAdapter,
columnsresize: true,
columns: [
{ text: 'LastName', datafield: 'LastName', width: 250 },
{ text: 'FirstName', datafield: 'FirstName', width: 150 },
{ text: 'Floor', datafield: 'Floor', width: 180 },
{ text: 'Office', datafield: 'Office', width: 120 }
]
});
});
</script>
HTML:
<div id='jqxWidget'>
<div id="grid"></div>
</div>
The issue here is how the $.ajax()
method is being used. AJAX is designed to be asynchronous which means that it executes but delegates handling of the response to a delegate function.
In the current code, both the dataAdapter
and the jqxGrid()
will execute directly after AJAX which may still be awaiting a response.
There are two ways to approach this
Relocate the setup of the dataAdapter
in the success:
delegate of the $.ajax()
method, this guarantees the data
variable is not bound to the dataAdapter
before a response is received.
In the $.ajax()
options pass async: false
which will make the AJAX call behave synchronously blocking until it receives a response. Be cautious however as this approach will lead to a poor user experience.
Personally, I prefer option 1 with a few adjustments to your code we can load the jqxGrid
without hindering the user by blocking#.
var data = ""
$(document).ready(function () {
$.ajax({
type: 'GET',
url: "compile_data.asp",
success:function(response){
data = response
alert(data)
// Grid will reload with returned data.
loadJqxGrid();
}
});
// Initial Grid load will be empty.
loadJqxGrid();
});
function loadJqxGrid() {
var source = {
datatype: "json",
datafields: [
{ name: 'LastName', type: 'string' },
{ name: 'FirstName', type: 'string' },
{ name: 'Floor', type: 'string' },
{ name: 'Office', type: 'string' }
],
localdata: data
};
var dataAdapter = new $.jqx.dataAdapter(source);
$("#grid").jqxGrid({
width: getWidth('Grid'),
source: dataAdapter,
columnsresize: true,
columns: [
{ text: 'LastName', datafield: 'LastName', width: 250 },
{ text: 'FirstName', datafield: 'FirstName', width: 150 },
{ text: 'Floor', datafield: 'Floor', width: 180 },
{ text: 'Office', datafield: 'Office', width: 120 }
]
});
}
# Provided untested