Render table from AJAX source failure (no errors)

Render table from AJAX source failure (no errors)

JMohJMoh Posts: 6Questions: 1Answers: 0

I can get DataTables working using AJAX calls and rendering the table in the success portion of those calls. However I'd like (somewhat stubbornly at this point) to use the features within DataTables to provide the same functionality. The issue is the table is not rendering any rows after the AJAX call.

HTML:
<table id="tbl" class="table table-bordered"></table>

JavaScript:

var prod = $("#prod").val();
$("#tbl").DataTable({
    pageLength: 25,
    ajax: {
        type: "POST",
        url: "api.aspx/GetData",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: function () {
            return "{prod: '" + prod + "'}";
        },
        dataSrc: function (result) {
            return $.parseJSON(result.d);
        }
    },
    columns: [
        { data: "Column1" },
        { data: "Column2" },
        { data: "Column3" },
        { data: "Column4" }
    ]
});

The API responds properly with d containing the entire JSON payload.

I first had issues with the AJAX.data functionality (AJAX error) where converting the standard AJAX "data" field to a function as seen above was the solution.
Any other formatting for dataSrc (i.e. using result.d alone, setting dataSrc to "d", etc.) all provide errors. The above configuration is error-free and the AJAX call is made and returns data properly, the table is initialized, but there is no data rendered (i.e. 0 rows in table).

I ran the debugger:

Data source:    Ajax
Processing mode:    Client-side
Draws:  1
Columns:    14
Rows - total:   0
Rows - after search:    0
Display start:  0
Display length: 25

There were no errors (beyond CSS warning about MAX-WIDTH, but I know the table can render the data as-is because I did it AJAX-first before trying the above method).

Any insight would be appreciated

Answers

  • JMohJMoh Posts: 6Questions: 1Answers: 0

    I could not recreate this issue using JSFiddle as the AJAX functionality is not recreate...able. I hope that doesn't affect the visibility of this question.

  • colincolin Posts: 15,240Questions: 1Answers: 2,599

    Hi @JMoh ,

    The thing to check would be the JSON that's being returned. Could you post it here, please.

    Cheers,

    Colin

  • JMohJMoh Posts: 6Questions: 1Answers: 0

    Hi @colin!

    Thanks for your reply. The raw data is coming in the following format:

    {
       "d":
       "[
            {
                \"Column1\":\"PA\",
                \"Column2\":\"XAL2Y2\",
                \"Column3\":\"BLK\",
                \"Column4\":\"2019\"
            }
        ]"
    }
    

    It's in string format, which is why I'm attempting to parse in the dataSrc attribute.

    JM

  • colincolin Posts: 15,240Questions: 1Answers: 2,599

    Hi @JMoh ,

    Yep, that'll do it - it's not valid JSON, try running it through a JSON validator. The backslashes shouldn't be there, so you would need to remove those. You should be able to use JSON.parse() as discussed in this thread.

    Cheers,

    Colin

  • JMohJMoh Posts: 6Questions: 1Answers: 0

    @colin ,

    I have another version of this same code where I'm manually making the AJAX call, then in the success I'm calling DataTable() with data: JSON.parse(result.d) and it works just fine. The JSON I posted to you has backslash delimiters from the server-side, but it's removed on the client-side when i run JSON.parse().

    I suspected the issue was with how DataTables uses the dataSrc attribute... is there a fundamental difference between standard AJAX.data and DataTables.AJAX.dataSrc?

    JM

  • kthorngrenkthorngren Posts: 21,344Questions: 26Answers: 4,954

    I tried JSON.parse(result.d) with your data here and it fails:
    https://jsfiddle.net/fj0a63qh/

    I copied the string into https://jsonlint.com/ and it fails with this:

    Error: Parse error on line 1:
    [{  \   "Column1\":\"PA\"
    ---^
    Expecting 'STRING', '}', got 'undefined'
    

    Looks like its being serialized twice. Maybe the last comment in this thread will help:
    https://datatables.net/forums/discussion/comment/117976/#Comment_117976

    Kevin

  • JMohJMoh Posts: 6Questions: 1Answers: 0
    edited March 2019

    Thank you for your time @kthorngren .

    However, the JSON within data.d looks like this:

    [
        {"Product":"AT","Model":"DMX980","Colour":"WHT","Year":"2019"},
        {"Product":"AT","Model":"DMX955","Colour":"GRY","Year":"2018"},
        {"Product":"AT","Model":"DMX990","Colour":"BLK","Year":"2018"}
    ]
    

    (It's not "column1" as suggested by first post, sorry I did that for simplicity).

    The above passes JSON validation, and works, here: https://jsfiddle.net/8mpL7gh1/

    The last JSON I pasted was the payload as shown by Firefox, which includes the quotation delimiting added by the server-side. The above JSON works when I call DataTable() in the Success portion of a separate AJAX call.

    The issue seems to be with how dataSrc uses the data. For example, JSON.parse(data.d) in the success of a separate AJAX call (all else equal) will work to generate DataTable(). Why is the same exact JSON.parse(data.d) not working within the dataSrc attribute of the AJAX property within DataTable()? The table just sits with "loading..." as row 1, despite the fully returned (200 status) AJAX call with valid JSON data sitting in the response.

    JM

  • kthorngrenkthorngren Posts: 21,344Questions: 26Answers: 4,954
    edited March 2019

    When I look at the ajax.dataSrc as a function example it doesn't use JSON.parse. It accesses the data directly. I would start by using console.log statements in the function to see whats happening, like this:
    http://live.datatables.net/xayuqowi/1/edit

    Maybe you don't need to parse it.

    Kevin

  • JMohJMoh Posts: 6Questions: 1Answers: 0
    edited March 2019

    Hey @colin and @kthorngren !

    The issue was because I was using success and beforesend. The documents say here (https://datatables.net/reference/option/ajax.dataSrc) that success is necessary for DataTables to render the table. I had to remove those callbacks for the table to render. Unfortunately this way won't likely work for me anyway because "prod" from my original post is likely to change. And the "prod" value as setup during the initial DataTables initialization seems to be fixed with the value set the first time it was loaded (and doesn't change when I run table.ajax.reload()).

    EDIT: I ended up with the following setup:

    var prod = $("#product").val();
     tbl = $("#tbl").DataTable({
        pageLength: 25,
        processing: true,
        ajax: {
             type: "POST",
             url: "ATPReport.aspx/GetData",
             contentType: "application/json; charset=utf-8",
             dataType: "json",
             data: function () {
                 return "{ prod: '" + prod + "'}";
             },
             dataSrc: function (result) {
                 return JSON.parse(result.d);
              }
        },
        columns: [
            { data: "Product" },
            { data: "Model" },
            { data: "Colour" },
            { data: "Year" }
         ]
    });
    

    Thanks again for your help.

    JM

This discussion has been closed.