9

Update: to avoid the possibility that the problem comes solely down to the same origin policy, I've tried serving this locally where all assets are coming from http://localhost:4000 using Serve. It didn't solve the problem. So editing the fiddle might not work because of the same origin policy, but you can see the code there.


I'm trying to use Dynatable to load external JSON, skipping the read/normalize step (which generates the JSON from an existing table). This is supposed to be supported, but it's not working for me.

Here's my attempt on JSFiddle. Loading JSON from within the document (which doesn't seem terribly useful to me) is working perfectly, as seen in the fiddle. But pulling it in from a URL is not working at all.

Here's my JavaScript:

// getting JSON from the document works, but of what use is that?
$(document).ready( function() {
    $('#local').dynatable({
        dataset: {
            records: JSON.parse($('#music').text())
        }
    });        
    // getting JSON from a remote source fails:
    $('#remote').dynatable({
        dataset: {
            ajax: true,
            ajaxOnLoad: true,
            ajaxUrl: '//www.dynatable.com/dynatable-ajax.json',
            records: []
        }
    });
});

...which refers to two tables, one with an id of "local" and another with an id of "remote", and to a script containing data for the local table:

<h3>Remote JSON: Failing</h3>
<table class="table table-striped" id="remote">
  <thead>
    <th>Some Attribute</th>
    <th>Some Other Attribute</th>
  </thead>
  <tbody>
  </tbody>
</table>
<hr>
<h3>Local JSON: Succeeding</h3>
<table class="table table-striped" id="local">
  <thead>
    <th style="color: black;">Band</th>
    <th>Album</th>
  </thead>
  <tbody>
  </tbody>
</table>
<script id="music">
[
    {
        "band": "The Police",
        "album": "Ghost In The Machine"
    },{
        "band": "Supertramp",
        "album": "Breakfast In America"
    },{
        "band": "Peter Tosh",
        "album": "Mama Africa"
    },{
        "band": "The Police",
        "album": "Regatta d'Blanc"
    },{
        "band": "The Police",
        "album": "Zenyatta Mondatta"
    },{
        "band": "Supertramp",
        "album": "Crime of the Century"
    },{
        "band": "Talking Heads",
        "album": "Remain in Light"
    },{
        "band": "Talking Heads",
        "album": "Speaking in Tongues"
    }
]
</script>
Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144
iconoclast
  • 21,213
  • 15
  • 102
  • 138
  • Here is a snapshot of your code with chrome running with "-disable-web-security" flag. http://imgur.com/Vcxz45e – Asad Hasan Jan 24 '14 at 17:43
  • Also keep in mind, a different port is a different origin. Thus page running on localhost:80 cannot access a resource from localhost:4000 – Asad Hasan Jan 24 '14 at 17:50
  • Good point about ports, but it isn't a problem here, as I'm serving everything from port 4000. – iconoclast Jan 24 '14 at 19:58

1 Answers1

6

The reason the remote isn't working is because when fetching data via AJAX, the response JSON must have some meta-data included with it along with the actual records.

If you look at the AJAX example in the dynatable docs, you can click "View AJAX Data" to see what the format looks like:

{
  "records": [
    {
      "someAttribute": "I am record one",
      "someOtherAttribute": "Fetched by AJAX"
    },
    {
      "someAttribute": "I am record two",
      "someOtherAttribute": "Cuz it's awesome"
    },
    {
      "someAttribute": "I am record three",
      "someOtherAttribute": "Yup, still AJAX"
    }
  ],
  "queryRecordCount": 3,
  "totalRecordCount": 3
}

You can see the actual results array is nested under "records" in the response JSON, and it also returns how many records are total in the set, as well as how many are in the current set.

The reason this meta-data is needed by dynatable is in order to do the pagination and the record-count text at the bottom of the table. Since your server is doing the actual querying, sorting, and paginating (e.g. via a database query or other server-side processing), dynatable only sees the final result. Therefore, dynatable wouldn't ever know:

  1. how many total records are in the set vs.

  2. how many records are in the filtered/queried set (across all pages) vs.

  3. how many records are in the filtered/queried paginated set (on the current page).

The only thing dynatable could infer from the returned results is (3) from above, i.e. how many records are in the filtered/queried set on the current page. So, it needs the returned JSON from the server to tell it (1), which is the totalRecordCount, and (2), which is the queryRecordCount.

Of course, if you don't want all of that, you can just turn off pagination and the record-count text, and tell dynatable that the results will be located at the root of the JSON returned by the server:

$('#remote').dynatable({
  features: {
    paginate: false,
    recordCount: false
  },
  dataset: {
    ajax: true,
    ajaxOnLoad: true,
    ajaxUrl: '//www.dynatable.com/dynatable-ajax.json',
    records: []
  },
  params: {
    records: '_root'
  }
});
jangosteve
  • 1,562
  • 2
  • 14
  • 26
  • Thanks! (I did notice that meta-data but had no idea it was required, since it wasn't present elsewhere. If that requirement is specified in the docs I just missed it.) – iconoclast Jan 24 '14 at 19:56
  • Another reason I left the metadata out is that I wasn't planning on making my server do the pagination etc. I just wanted to skip the HTML-to-JSON step, since my app server is gonna be pulling the data from a web service as JSON, and it doesn't make sense to go JSON-->HTML-->JSON if I can just pass the whole thing through to the browser as JSON. Is this not possible? Am I required to either convert to HTML, or else serve the browser a page of JSON at a time? – iconoclast Jan 24 '14 at 20:05
  • That's a good point, I'll update the docs to be more clear about the format for AJAX mode. – jangosteve Jan 27 '14 at 04:24
  • 2
    What you're looking to do then is to not use actual AJAX mode, as that assumes that all the processing will be taking place on your server and delegates it accordingly. What you want is non-AJAX mode, but to load your initial dataset via AJAX. In that case, use the [Existing JSON](http://www.dynatable.com/#existing-json) example, but put that code inside a [`$.getJSON()`](http://api.jquery.com/jquery.getjson/) success callback. – jangosteve Jan 27 '14 at 04:26
  • @jangosteve - just to be clear, I need to properly format my JSON response to match what you have in your docs: `{'records':[]...}`? Is there a way to override this? – cheshireoctopus Sep 08 '14 at 19:53
  • 1
    @cheshireoctopus Yes, you can configure the format of the JSON via the `params` object in the config [(see configuration docs)](http://www.dynatable.com/#configuration). If you want your JSON to just be an array of records, set the `params.records` value to "_root". See the last example in my post. – jangosteve Sep 09 '14 at 20:01