How to allow user to upload their own JSON file?

How to allow user to upload their own JSON file?

responsivelabsresponsivelabs Posts: 31Questions: 8Answers: 0

So I've been developing a portion of a project with datatables, and I've been trying to find a way to upload a JSON file on the client side and have it render in datatables. Preferably, im trying to do this all on the client side so I don't have to save all the JSON files that people upload. Anyone have any suggestions on this? Would greatly be appreciated.

This question has accepted answers - jump to:

Answers

  • kthorngrenkthorngren Posts: 21,327Questions: 26Answers: 4,949
    Answer ✓

    Uploading a JSON file is not a built in feature of Datatables. This SO Thread may help you with that process. Once Uploaded you can use JSON.parse() to parse the uploaded JSON string, store it in a Javascript variable then use rows.add() to add to an already initialized Datatable or use data when initializing. Here is an example:
    https://datatables.net/examples/data_sources/js_array.html

    Kevin

  • responsivelabsresponsivelabs Posts: 31Questions: 8Answers: 0

    Ah gotcha - What about allowing the user to type in a file name or URL in place of uploading the json?

    Thanks for the info so far, very helpful.

  • kthorngrenkthorngren Posts: 21,327Questions: 26Answers: 4,949
    edited January 2020

    There is an example, in the thread, allowing the user to browse local files. Does something like that not work?

    The process to obtain the JSON data is outside the scope of Datatables. You will be better served to look for a solution on Stack Overflow to meet your upload needs. Once you have that working then we can help get it into Datatables.

    If you haven't done so already you will want to read the Data Manual to understand the structures Datatables supports.

    Kevin

  • responsivelabsresponsivelabs Posts: 31Questions: 8Answers: 0
    edited January 2020

    Ok, so i've managed to figure this out using the following:


    document.getElementById('import').onclick = function() {
        var files = document.getElementById('selectFiles').files;
      console.log(files);
      if (files.length <= 0) {
        return false;
      }
      
      var fr = new FileReader();
      
      fr.onload = function(e) { 
      console.log(e);
        var result = JSON.parse(e.target.result);
        var formatted = JSON.stringify(result, null, 2);
            document.getElementById('result').value = formatted;
      }
      
      fr.readAsText(files.item(0));
    };
    

    So I presume now I would need to use the rows.add() function? And yes datatables will already be initialized since this is a feature I'm adding for users to essentially see their JSON file in a specifically rendered format.

    Edited by Kevin:  Syntax highlighting. Details on how to highlight code using markdown can be found in this guide

  • kthorngrenkthorngren Posts: 21,327Questions: 26Answers: 4,949

    Yes, the result variable in line 12 should have the data you can add via rows.add(). The key is to make sure the JSON data is an array containing either arrays or objects. For example:
    http://live.datatables.net/tahiquyi/1/edit

    Kevin

  • responsivelabsresponsivelabs Posts: 31Questions: 8Answers: 0
    edited January 2020

    Hmm, i'm having trouble trying to find out where to use the table.rows.add function in conjunction with what I've already got:

        var arrayReturn = [];
                $.ajax({
                    url: "file.json",
                    async: false,
                    dataType: 'json',
                    success: function (data) {
                        for (var i = 0, len = data.length; i < len; i++) {
                            var desc = data[i].body;
                            arrayReturn.push([ data[i].data1, data[i].data2, data[i].data3, data[i].data4+'x', data[i].payout, data[i].data5, data[i].updatedAt, '<a href="id='+data[i].id+'&modal" target="_blank">View</a>']);
                        }
                    inittable(arrayReturn);
                    }
                });
        function inittable(data) {  
            //console.log(data);
            $('#MainTable').DataTable( {
                "aaData": data,
                "deferRender": true,
                "dataSrc": function ( json ) {
                    console.log(json);
                  for ( var i=0, ien=json.data.length ; i<ien ; i++ ) {
                    json.data[i][0] = '<a href="/message/'+json.data[i][0]+'>View message</a>';
                  }
                  return json.data;
                }
            } );
        }
    
  • responsivelabsresponsivelabs Posts: 31Questions: 8Answers: 0
    edited January 2020

    btw I'm doing it in this manner bc I'm selectively using certain data from the JSON file rather than rendering all of it.

    Also I removed async: false - not sure why I had that in there

  • responsivelabsresponsivelabs Posts: 31Questions: 8Answers: 0

    Currently when I load the page I just receive the array upon outputting the results into console:
    (641) […] [0…99] [100…199] [200…299] [300…399] [400…499] [500…599] [600…640] length: 641 <prototype>: Array [] data.html:103:11

  • kthorngrenkthorngren Posts: 21,327Questions: 26Answers: 4,949
    Answer ✓

    i'm having trouble trying to find out where to use the table.rows.add function in conjunction with what I've already go

    Looks like you should add it here:

    document.getElementById('import').onclick = function() {
        var files = document.getElementById('selectFiles').files;
      console.log(files);
      if (files.length <= 0) {
        return false;
      }
       
      var fr = new FileReader();
       
      fr.onload = function(e) {
      console.log(e);
        var result = JSON.parse(e.target.result);
    
        $('#MainTable').DataTable().rows.add( result ).draw();
    
        var formatted = JSON.stringify(result, null, 2);
            document.getElementById('result').value = formatted;
      }
       
      fr.readAsText(files.item(0));
    };
    

    This assumes the JSON data is in a format your table supports. You may need to iterate the result and manipulate it to load properly into the table.

    Kevin

  • responsivelabsresponsivelabs Posts: 31Questions: 8Answers: 0

    Awesome, so I've definitely made some progress Kevin :) Looks like its loading the file now into datatables, its just that I get the following warning:

    DataTables warning: table id=betMain - Requested unknown parameter '0' for row 641

    I presume this is because the needs to be formatted to fit the table?

  • kthorngrenkthorngren Posts: 21,327Questions: 26Answers: 4,949

    The link in the alert provides details:
    https://datatables.net/manual/tech-notes/4

    But yes, each row needs to match the Datatbles config. I wonder if line 641 is the end of the file with a blank line. It may be slower but you could loop through the result data, validate or manipulate as needed, then use row,add() and add the rows one at a time. Like this:

    var table = $('#MainTable').DataTable();
    for (i=0; i<result.length; i++) {
      var rowData = result[i];
      // Process and validate `rowData`
      // if rowData is valid then
      table.row.add( rowData );
    }
    table.draw(); // Do this once after the loop.
    

    Kevin

  • responsivelabsresponsivelabs Posts: 31Questions: 8Answers: 0
    edited January 2020

    Well currently, Im not using all of the data in the JSON file. Im selectively choosing certain data points and rendering just those, which I'm doing originally with:

    for (var i = 0, len = data.length; i < len; i++) {
                            var desc = data[i].body;
                            arrayReturn.push([ data[i].nonce, data[i].game, data[i].amount, data[i].payoutMultiplier+'x', data[i].payout, data[i].currency, data[i].updatedAt, '<a href="id='+data[i].id+'&modal" target="_blank">View</a>']);
                        }
    

    How would I go about just extracting certain data like I'm doing for the original file its loading? Currently I see where the rows should be but all the data is blank.

    Sorry about all the questions, Im so close to getting this to work - really hoping I can get it proper today!

  • kthorngrenkthorngren Posts: 21,327Questions: 26Answers: 4,949

    How would I go about just extracting certain data like I'm doing for the original file its loading? Currently I see where the rows should be but all the data is blank.

    My previous post has an example. If the rows are blank then the row data is probably not what you expect. Console.log statements should help you discover what you have. How does it differ from your initial data?

    If you need help then post a few rows of your data so we can take a look.

    Kevin

  • responsivelabsresponsivelabs Posts: 31Questions: 8Answers: 0

    Hmm I tried that but its not outputting anything to the table. I've even tried removing all the extra data in the JSON and just doing one row but still nothing. Below is an example of the JSON file i'm testing:

    [{"id":"456974fb-eb2e-40ce-bd03-e34153365975","game":"new","nonce":2161,"currency":"usd"}]
    

    Eventually though this is what the file would look like with a row containing all the data:

    [{"id":"15110e2ea8ed","game":"new","nonce":2383,"currency":"usd","amount":0.003,"payoutMultiplier":0,"payout":0,"createdAt":"2020-01-27T01:03:26.771Z","updatedAt":"2020-01-27T01:03:26.771Z","stateGame1":{"drawnNumbers":[10,3,1,35,36,14,15,16,27,30],"selectedNumbers":[13,11,2,0,26,30,17,21,20],"risk":"high"},"serverSeedHash":"b27698668f15be8809588564951425c942d91b8b8467fa51ed459d2a6d2a1091","clientSeed":"d17"}]
    
    
  • responsivelabsresponsivelabs Posts: 31Questions: 8Answers: 0

    Btw, to make things easier here it is in action:

    http://live.datatables.net/zeziqiyi/1/edit?html,css,js,console,output

    For the JSON, I just copied the following and put it into the file example.json for upload. It seems to add the rows but no data at the moment.

    [{"id":"456974fb-eb2e-40ce-bd03-e34153365975","game":"new","nonce":2161,"currency":"usd"}]
    
  • responsivelabsresponsivelabs Posts: 31Questions: 8Answers: 0

    Also here is a better formatted version of a row from the JSON file so you can easily see:

    {
            "id": "45974fb-eb2e-40ce-bd03-e34153975",
            "game": "new",
            "nonce": 2161,
            "currency": "usd",
            "amount": 1,
            "payoutMultiplier": 0,
            "payout": 0,
            "createdAt": "2020-01-26T23:59:58.526Z",
            "updatedAt": "2020-01-27T00:00:07.543Z",
            "stateGame1": {
                "rounds": [{
                    "card": 26,
                    "guess": "lowerEqual",
                    "payoutMultiplier": 0
                }],
                "startNumber": 9
            },
            "serverSeedHash": "b27698668f15be8809588564951425c942d91b8b8467fa51ed459d2a6d2a1091",
            "clientSeed": "d17"
        }
    
  • kthorngrenkthorngren Posts: 21,327Questions: 26Answers: 4,949
    Answer ✓

    here is a better formatted version of a row from the JSON file so you can easily see:

    Thanks for formatting it :smile: This is object based but your Datatables is not configured for objects by using columns.data. Looks like your initial data you loop through and turn into array based data. You need to be consistent with this as Datatables doesn't support both in the same table at the same time.

    I would look at removing the loop for the initial data. Use columns.data to define the columns and use columns.render to build '<a href="id='+data[i].id+'&modal" target="_blank">View</a>' in the last column.

    Kevin

  • responsivelabsresponsivelabs Posts: 31Questions: 8Answers: 0

    Ah dang, so I'm gonna most likely need to redo the initial data to use columns.data and columns.render? Was hoping I wouldn't have to redo it as I couldn't get it to work with the columns.data option for some reason :/

    What about changing the secondary data to mimic the initial data?

  • kthorngrenkthorngren Posts: 21,327Questions: 26Answers: 4,949

    The choice is yours. You can do either option. They just need to be the same structure.

    Kevin

  • responsivelabsresponsivelabs Posts: 31Questions: 8Answers: 0

    FINALLY got it working :) Decided to just go ahead and replace the initial data loop with the columns.data option. I haven't had a chance yet to use the columns.render for the HTML markup required for certain entries, however I can say that its rendering the data properly from the initial JSON file, and its also adding new rows successfully when uploading a new file.

    I'm sure I'll have other questions along the way as this is a work in progress, but I really appreciate your help with this Kevin. Definitely would have taken me 10x longer without your assistance :smile:

  • kthorngrenkthorngren Posts: 21,327Questions: 26Answers: 4,949

    Glad you got it working!

    Kevin

This discussion has been closed.