jqGrid loadonce doesn't work with asp.net
Asked Answered
T

4

2

Does anyone know how to solve this nasty issue with asp.net+asmx+jqGrid sorting. Because, in order to call pagemethods or asmx web services from jqGrid, it needs to be hacked like this:

datatype: function() {
                    $.ajax({
                        url: 'Default.aspx/GetPersons',
                        data: "{}",
                        type: "POST",
                        dataFilter: function(data) {
                            var msg = eval('(' + data + ')');
                            if (msg.hasOwnProperty('d'))
                                return msg.d;
                            else
                                return msg;
                        }

instead of this:

datatype: "json"

Because of that, setting loadonce attribute to true in order to do my sortings on the client, doesn't work and jqGrid calls server for every event that occur in grid.

Any ideas?

Thanx Marko

Tycoon answered 25/8, 2009 at 15:23 Comment(0)
M
2

I eventually gave up on JSON (with ASP.NET) and just used XML. Then everything just works. Make sure the return type from your asmx is XmlDocument

A good summary of everything you need to do to make it work (on the client side at least) can be found on the the JQGrid wiki

Look at their sample XML and make sure what your service returns a buffer (best to validate with Fiddler) that follows the same schema.

UPDATE - Some Code samples

Here is the client side script to create the grid

     var mygrid = $("#list").jqGrid({
      url: '../../webServices/callsGridService.asmx/getCallsGridDataXML?nd=' + new Date().getTime(),
      datatype: 'xml',
      mtype: 'POST',
      contentType: "text/xml",
      colNames: ['Call ID', 'Date / Time', 'Duration'],
      colModel: [
      { name: 'callId', index: 'callId', align: "right", key: true },
  { name: 'callTime', index: 'callTime', sorttype: 'date' },
      { name: 'duration', index: 'duration', align: "right" }
    ],
      pager: $('#pager'),
      rowNum: 10,
      rowList: [10, 25, 50, 100],
      sortname: 'callTime',
      viewrecords: true,
      sortorder: "desc",
      height: "100%",
      multiselect: true,
      rownumbers: true,
      gridview: true,
      autowidth: true,
      caption: "Calls"
    })

And here is the service code (VB.NET):

  Public Function getCallsGridDataXML() As XmlDocument
    Dim xmlRet As New XmlDocument
    Dim ret As New StringBuilder

    m_pageNum = CInt(HttpContext.Current.Request.Form.Item("page"))
    If m_pageNum = Nothing OrElse m_pageNum = 0 Then
      m_pageNum = 1
    End If
    m_pageSize = CInt(HttpContext.Current.Request.Form.Item("rows"))
    If m_pageSize = Nothing OrElse m_pageSize = 0 Then
      m_pageSize = 10
    End If
    m_sortItem = CStr(HttpContext.Current.Request.Form.Item("sidx"))
    m_sortOrder = CStr(HttpContext.Current.Request.Form.Item("sord"))

    Dim dt As DataTable
    dt = Session(SESSION_CALLS_GRID_DATA)

    Dim myView As DataView = dt.DefaultView
    If m_sortItem IsNot Nothing AndAlso m_sortOrder IsNot Nothing Then
      myView.Sort = m_sortItem & " " & m_sortOrder
    End If

    ret.Append("<?xml version='1.0' encoding='utf-8'?>")
    ret.Append("<rows>")
    ret.Append("<page>" & m_pageNum & "</page>")
    ret.Append("<total>" & Math.Floor(dt.Rows.Count / m_pageSize) & "</total>")
    ret.Append("<records>" & dt.Rows.Count & "</records>")

    For i As Integer = (m_pageNum - 1) * m_pageSize To Math.Min(dt.Rows.Count - 1, m_pageNum * m_pageSize - 1)
      ret.Append("<row>")
      Dim cellCount As Integer = 0

      ret.Append("<cell>" & Server.HtmlEncode(myView(i)("callId")) & "</cell>")
      ret.Append("<cell>" & Server.HtmlEncode(myView(i)("callTime")) & "</cell>")
      ret.Append("<cell>" & Server.HtmlEncode(myView(i)("duration")) & "</cell>")

      ret.Append("</row>")
    Next

    ret.Append("</rows>")
    xmlRet.LoadXml(ret.ToString)
    Return xmlRet
   End Function

You can see I'm building the XML as a string and then loading it into the XMLDocumennt. I can't say I know this is the best way. You could build the XML DOM directly on the document.

Morelos answered 25/8, 2009 at 19:25 Comment(2)
hmm, nice tip :) I would try xml-way for sure... thanxTycoon
could you please post portion of your code when you are using xml...thanxTycoon
F
7

It's a little bit late, but here's a (the?) super-easy solution for any future solution-seekers:

gridComplete: function(){ 
  $("#yourGridID").setGridParam({datatype: 'local'}); 
}

That's it. I'm using 3.7.2, can't speak for any other versions. The problem (apparently) stems from 'loadonce' only working with the pre-defined datatype values, which a function is not. I believe the other built-in values will also work, but 'local' makes sense.

Furthest answered 17/8, 2010 at 15:47 Comment(5)
Thanks! I have datatype as a function. Setting datatype:local at gridcomplete works for me!Turley
@Groxx: This works for me but only for one column :S. Would you happen to know why?Forney
@DavidS: It only sorts for one column? Not sure. I can look into it a bit though, if you provide a bit more info: is it always the same column? In the same position? Do others just not do anything, or do they hit the server? Any other possibly-relevant settings? And what version? The code is messy, and version matters at strange times.Furthest
@Groxx: It is always the same column but I don't know what you mean by same position. The others don't "really" do anything. After I change the sort order for the column that works and I click on any of the other columns, the sorting reverts back to the state when I first view the grid. I am not sure what the relevant settings might be as I just started using jqGrid yesterday. The version I'm using is 4.1.1.Forney
jqGrid is a pain :) It does work though. I wish there were something better I could point you towards instead, but I don't know of any. As to same position, I mean the column location - left-most, 3rd, something like that. I understand the problem now though, I'll take a peek when I next get time, and let you know what I find.Furthest
M
2

I eventually gave up on JSON (with ASP.NET) and just used XML. Then everything just works. Make sure the return type from your asmx is XmlDocument

A good summary of everything you need to do to make it work (on the client side at least) can be found on the the JQGrid wiki

Look at their sample XML and make sure what your service returns a buffer (best to validate with Fiddler) that follows the same schema.

UPDATE - Some Code samples

Here is the client side script to create the grid

     var mygrid = $("#list").jqGrid({
      url: '../../webServices/callsGridService.asmx/getCallsGridDataXML?nd=' + new Date().getTime(),
      datatype: 'xml',
      mtype: 'POST',
      contentType: "text/xml",
      colNames: ['Call ID', 'Date / Time', 'Duration'],
      colModel: [
      { name: 'callId', index: 'callId', align: "right", key: true },
  { name: 'callTime', index: 'callTime', sorttype: 'date' },
      { name: 'duration', index: 'duration', align: "right" }
    ],
      pager: $('#pager'),
      rowNum: 10,
      rowList: [10, 25, 50, 100],
      sortname: 'callTime',
      viewrecords: true,
      sortorder: "desc",
      height: "100%",
      multiselect: true,
      rownumbers: true,
      gridview: true,
      autowidth: true,
      caption: "Calls"
    })

And here is the service code (VB.NET):

  Public Function getCallsGridDataXML() As XmlDocument
    Dim xmlRet As New XmlDocument
    Dim ret As New StringBuilder

    m_pageNum = CInt(HttpContext.Current.Request.Form.Item("page"))
    If m_pageNum = Nothing OrElse m_pageNum = 0 Then
      m_pageNum = 1
    End If
    m_pageSize = CInt(HttpContext.Current.Request.Form.Item("rows"))
    If m_pageSize = Nothing OrElse m_pageSize = 0 Then
      m_pageSize = 10
    End If
    m_sortItem = CStr(HttpContext.Current.Request.Form.Item("sidx"))
    m_sortOrder = CStr(HttpContext.Current.Request.Form.Item("sord"))

    Dim dt As DataTable
    dt = Session(SESSION_CALLS_GRID_DATA)

    Dim myView As DataView = dt.DefaultView
    If m_sortItem IsNot Nothing AndAlso m_sortOrder IsNot Nothing Then
      myView.Sort = m_sortItem & " " & m_sortOrder
    End If

    ret.Append("<?xml version='1.0' encoding='utf-8'?>")
    ret.Append("<rows>")
    ret.Append("<page>" & m_pageNum & "</page>")
    ret.Append("<total>" & Math.Floor(dt.Rows.Count / m_pageSize) & "</total>")
    ret.Append("<records>" & dt.Rows.Count & "</records>")

    For i As Integer = (m_pageNum - 1) * m_pageSize To Math.Min(dt.Rows.Count - 1, m_pageNum * m_pageSize - 1)
      ret.Append("<row>")
      Dim cellCount As Integer = 0

      ret.Append("<cell>" & Server.HtmlEncode(myView(i)("callId")) & "</cell>")
      ret.Append("<cell>" & Server.HtmlEncode(myView(i)("callTime")) & "</cell>")
      ret.Append("<cell>" & Server.HtmlEncode(myView(i)("duration")) & "</cell>")

      ret.Append("</row>")
    Next

    ret.Append("</rows>")
    xmlRet.LoadXml(ret.ToString)
    Return xmlRet
   End Function

You can see I'm building the XML as a string and then loading it into the XMLDocumennt. I can't say I know this is the best way. You could build the XML DOM directly on the document.

Morelos answered 25/8, 2009 at 19:25 Comment(2)
hmm, nice tip :) I would try xml-way for sure... thanxTycoon
could you please post portion of your code when you are using xml...thanxTycoon
T
2

Thanx a lot harlev...also for others one tip, you can set grid to work on client with

datatype: 'clientside'

attribute. I didn't find it at first because is not listed in online documentation but it is in pdf documentation which you can download from here.

Cheers

Tycoon answered 27/8, 2009 at 16:35 Comment(1)
yes even though the PDF isn't as up to date it has much more information!Ljoka
A
0

For those to whom @Groxx's solution didn't work (when I tried it the content of my grid dissapeared every time I tried to sort a column), try the solution from this thread. It worked for me. I'm using jqGrid 4.5.4.

First, set loadonce : true in your grid's settings. As explained here, this changes the datatype parameters to 'local' after the grids finishes loading for the first time. Then, when you want to reload the grid, change datatype back to json:

$('#your-grid').setGridParam({ datatype : 'json' }).trigger('reloadGrid');

If you are using navGrid you may want to review your add, edit and delete options to force your grid to reload like indicated in this answer.

Antigone answered 8/1, 2014 at 16:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.