2

I'm using jQuery and tabulator to create a fairly simple webpage showing the progress of various live events. I have three table elements on the page showing events in different states. Broadly speaking I have a table for events that are 'Live', 'Finished' and 'Upcoming'.

The tabulator code for each table looks a bit like this:

var eventTable = {
  layout:"fitColumns",
  columns:[
    {title:"Event ID", field:"eventID"},
    {title:"Event name", field:"eventName"},
    {title:"Event status", field:"eventStatus"}
  ]
};

I can then generate and populate the tables using data retrieved from the server using an AJAX call:

$('#live-events-table').tabulator(eventTable);
$('#live-events-table').tabulator("setData", "/cgi-bin/getevents.py");
$('#live-events-table').tabulator("setFilter", "status", "in", ["intermission", "mid-event"]);

Then similar code for the finished and upcoming tables.

This creates three requests for getevents.py every time the page is updated. This is undesirable because the data is pulled from another API and I want to avoid sending multiple identical requests. Also, there's a (small) chance the data could change between requests.

Is there a way of using the same data to populate all three tables?

toryan
  • 435
  • 5
  • 15

3 Answers3

2

Learnt something today. Never heard of Tabulator. I've been using DataTables for this sort of advanced tabular layout in the form of a jQuery plugin. Tabulator looks promising. Will have to explore more in the future.

In the docs I see Tabulator - Set Table Data, lots of alternative options available to set the data.

Hope I am understanding the problem correctly.

My thoughts/flow for tacking this problem would be:

  • Assuming your doing this already: Prep server side (getevents.py) needs to return all 'Live', 'Finished' and 'Upcoming' rows in JSON together in 1 response. How do I make a JSON object with multiple arrays?.

  • Client side on doc ready(), makes a jQuery ajax call to fetch this data before 3 x tabulators are built/called.

  • You can use a loading indicator. So the client sees something is happening in the 3 x before replaced by jQuery tabulator once the data is returned and you built with tabulator.

  • In the ajax success callback function you can iterate over the returned json object (containing the 3 x eventTypes). You might have to JSON.parse() if you store it in a JavaScript variable to iterate over.

  • Now get your specific array of event types nested objects arrays/json.

  • Then call your tabulator creation methods using the setData pointing to each specific JavaScript array containing the relevant data.

Not sure if this falls under "premature optimization", but I would proceed as the problem itself is rather fun to solve, but you know the requirements/needs better than I.

Good luck.

RoryGS
  • 1,572
  • 2
  • 7
  • 7
  • 1
    Thanks for this. Tabulator handles the loading indicator and filtering the JSON data for itself, and getevents.py returns everything ready for Tabulator to filter. I considered iterating through the json response to produce three datasets, but this seemed like duplicating work. I did manage to wrap the table construction in an ajax call on ready(), which I will post as an answer for future reference :) – toryan Aug 14 '18 at 01:45
  • @toryan A pleasure, very high level, didn't want to steal the fun from the problem. My thoughts RE indicator were that since the user now waits for you to fetch the info from getevents.py and waits for you to do whatever with the data and then build the tabulator objects you might still want a placeholder showing stuff is happening. As that might be the slowest part. Tabulator wouldn't handle the loading if you do it this way since your using your own custom ajax fetch and build process in order to share the data returned. – RoryGS Aug 14 '18 at 08:10
  • Regarding the iterating through the JSON response, I was thinking you use JSON.parse(), to convert the raw JSON string to a JavaScript array object, depending on the JSON structure you should be able to fetch the individual event types sub arrays and store in JavaScript array to work with. The tabulator doc above shows they accept a JS array object or JSON string. So you could split it to 3 arrays. Should be to much work I would think. Happens quickly on the client side. – RoryGS Aug 14 '18 at 08:15
  • Two other good answers to consider/read through. 1) https://stackoverflow.com/questions/11922383/access-process-nested-objects-arrays-or-json 2) https://stackoverflow.com/questions/4935632/parse-json-in-javascript * JSON.parse() * JSON.stringify() – RoryGS Aug 14 '18 at 08:20
  • Typo: "Should be to much work I would think. Happens quickly on the client side." was meant to be "Should**n't** be to much work I would think. Happens quickly on the client side." I should also not have posted links in comments, looks ugly. Same with the 2 x JSON functions. – RoryGS Aug 14 '18 at 08:26
1

I fixed this fairly simply, using suggestions from @RoryGS.

Define the table options in a variable, as before:

var eventTable = {
  layout:"fitColumns",
  columns:[
    {title:"Event ID", field:"eventID"},
    {title:"Event name", field:"eventName"},
    {title:"Event status", field:"eventStatus"}
  ]
};

Then make a jQuery ajax call to fetch the data, and build the table(s) in the success option of the function:

$(function() {
  $.ajax({
    dataType: "json",
    url: "/cgi-bin/getevents.py",
    success: function(data, status){
      $('#live-events-table').tabulator(eventTable);
      $('#finished-events-table').tabulator(eventTable);
      $('#live-events-table').tabulator("setData", data);
      $('#live-events-table').tabulator("setFilter", "status", "in", ["intermission", "mid-event"]);
      $('#finished-events-table').tabulator("setData", data);
      $('#finished-events-table').tabulator("setFilter", "status", "in", ["post-event"]);
    }
})})

It seems to be necessary to set the data individually for each table. I would like to specify the data in the constructor, but this doesn't seem to work. I will continue to try to refine this.

toryan
  • 435
  • 5
  • 15
  • Now keep in mind if the ajax call takes a very long time to load, your user will see a page without the tabulator loading indicators. Best way to test this is in your getevents.py set a sleep of 10 or 20 seconds. The tabulator calls happen only on success and that could take a unknown period of time. Unless I am missing something. – RoryGS Aug 14 '18 at 08:29
  • In the ajax success you could split the returned data up into 3 separate arrays as mentioned in above comments. From the docs "Tabulator row data is defined as an array of objects, that can either be passed as an array or retrieved as a JSON formatted string". But the way you are doing it looks good to me, depending on your requirements. Re the constructor it should work might just require some work. Good luck – RoryGS Aug 14 '18 at 08:38
1

If you are getting the data from a URL you can pass it into the ajaxURL property in the table constructor and tabulator will make the request for you:

$("#example-table").tabulator({
    ajaxURL:"/cgi-bin/getevents.pyw", //ajax URL
    columns:[...] //define columns etc
});
Oli Folkerd
  • 7,510
  • 1
  • 22
  • 46