9

I'm trying to write some simple Javascript that uses the Trello API to get all boards / lists / cards from my account and add them into an sortable table (using the Datatables jquery plugin).

I've so far managed to write a jsfiddle that gets all this information and writes it to a page, but I can't work out how to store all this information into some sort of data structure that can then be passed to the datatable plugin.

This is the fiddle I have so far that gets the data from Trello:

JS Fiddle Link

var carddata = [];

Trello.members.get("me", function(member) {
$("#fullName").text(member.fullName);

var boardUrl = "";

boardUrl = "members/me/boards";

Trello.get(boardUrl, function(boards) {

  $.each(boards, function(ix, board) {

    Trello.get("/boards/" + board.id + "/lists", function(lists) {
      $.each(lists, function(ix, list) {
        Trello.get("lists/" + list.id + "/cards", function(cards) {

          $.each(cards, function(ix, card) {
            console.log("boardname: " + board.name + "; list name: " + list.name + "; card name: " + card.name);

            carddata.push(
              "boardname: " + board.name + 
              "; list name: " + list.name + 
              "; card name: " + card.name
            );

            var $tablerow = "";

            $tablerow = $(
              "<tr><td>" + board.name + 
              "</td><td>" + list.name + 
              "</td><td>" + card.name + 
              "</td></tr>"
            ).appendTo("#table_body");

          });
          /*
                        for (i = 0; i < carddata.length; i++) {
                          console.log("carddata: " + carddata[i]);
                        }
          */
        });

      });

    });

  });

});

});

// **** carddata array is empty at this point ****
for (i = 0; i < carddata.length; i++) {
 console.log("carddata: " + carddata[i]);
}

It loops through all boards, lists and cards and currently adds what it finds to a html table (and also an array). I then use the Datatables plugin to change that HTML table into a sortable table.

However the plugin is seeing the HTML table as empty (from what I can see), I presume this is because of something like the plugin code being called before the Javascript builds up the table in HTML.

So instead I planned to add all the data into an array, and then pass that array into the datatable as a datasource, but I can 't see how to make the array accessible outside the very inner loop. From doing some searches I think this is to do with closures and scope but I'm struggling to understand how they work (I'm very new to Javascript).

Is anyone able to help me get this basic code working and show me what I'm doing wrong?

Thanks, David.

n1stre
  • 5,856
  • 4
  • 20
  • 41
David Letts
  • 103
  • 5
  • 1
    Your `carddata` array won't be altered until all of the GET requests are done. `$.get` is an asynchronous method, meaning it will run after every other synchronous procedure in the rest of your script. You should read about AJAX and callbacks in JavaScript. – glhrmv Jun 01 '17 at 12:49
  • Also, you don't need to iterate over an array to print it to the console, in JavaScript. Just `console.log(carddata)` should work fine. – glhrmv Jun 01 '17 at 12:50
  • OK thanks Dogui. I've been looking at examples of callbacks but am struggling to apply them to my specific case - do you know of any resources or examples that would help (beyond the usual searches) – David Letts Jun 01 '17 at 14:30
  • Hopefully this video will help you: [What the heck is the event loop anyway?](https://www.youtube.com/watch?v=8aGhZQkoFbQ) – glhrmv Jun 01 '17 at 14:35
  • OK thanks for that video dogui - it looks very useful from just skipping through it. I'll put some time aside to watch it and see if it helps. – David Letts Jun 02 '17 at 07:43

1 Answers1

0

The following code snippet demonstrate how to add data to data table after table created. For how to wait for all asyn requests completed, setTimeout is used to simulate Trello.get method for the asyn behavior.

var boardHash = {};
var listHash = {};

var updateLoggedIn = function() {
  $("#loggedout").toggle(!isLoggedIn);
  $("#loggedin").toggle(isLoggedIn);
};

var loadCardData = function(){
 var carddata = [];
 var loadMember = function() {
  setTimeout(function(){
   console.log("Member loaded");
   loadBoard();
  },2000);
 }
 
 var loadBoard = function() {
  
  setTimeout(function(){
   console.log("Boards loaded");
   var listPromises = [];
   loadList(["boardA","boardB","boardC"],listPromises);
   $.when.apply($, listPromises).then(function(){
     table.rows.add(carddata).draw("");
   });
  },1000);
 };
 
 var loadList = function(boards,listPromises){
  $.each(boards,function(boardIndex, boardValue){
   var listDefered = $.Deferred();
   listPromises.push(listDefered.promise());
   setTimeout(function(){
    console.log(boardValue+" lists loaded");
    var cardPromises = [];
    loadCard(["listA","listA","listC"],boardValue,cardPromises);
    $.when.apply($, cardPromises).then(function(){
     listDefered.resolve();
    });
   },(boardIndex+1)*900);
  });
 };
 
 var loadCard = function(lists,boardValue,cardPromises){
  $.each(["listA","listA","listC"],function(listIndex, listValue){
   var cardDefered = $.Deferred();
   cardPromises.push(cardDefered.promise());
   setTimeout(function(){
    console.log(boardValue+" "+listValue+" cards loaded"); 
    $.each(["cardA","cardB","cardC"],function(cardIndex, cardValue){
     carddata.push({
      "boardName":boardValue,
      "listName":listValue,
      "cardName":cardValue
     });
    });
    cardDefered.resolve();
   },(listIndex+1)*800);
  });
 };
 loadMember();
 };

var logout = function() {
  updateLoggedIn();
};


$("#connectLink")
  .click(function() {
   loadCardData();
  });

$("#disconnect").click(logout);

var consoleLine = "<p class=\"console-line\"></p>";

console = {
  log: function(text) {
    $("#console-log").append($(consoleLine).html(text));
  }
};
var table = null;
$(document).ready( function () {
    table = $('#table_id').DataTable({
  columns: [
        { data: 'boardName' },
        { data: 'listName' },
        { data: 'cardName' }
  ]
 });
} );
<html>

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <link href="//cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet" />
  <script src="//cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>

  <div id="loggedout">
    <a id="connectLink" href="#">Connect To Trello</a>
  </div>
</head>
<div id="loggedin">
  <div id="header">
    Logged in to as <span id="fullName"></span>
    <a id="disconnect" href="#">Log Out</a>
  </div>

  <div id="output"></div>
</div>

<table id="table_id" class="display" border=1>
  <thead>
    <tr>
      <th>Board</th>
      <th>List</th>
      <th>Card</th>
    </tr>
  </thead>
  <tbody id="table_body">

  </tbody>
</table>

<div id="console-log"></div>

</html>

For adding data to data table

So in your code, add the columns options to the data table, and use rows.add method to add data to data table when all ajax request are done.

Wait for all ajax request completed

The most tricky part is how to ensure all response are done, this can be achieved by $.Deferred() and $.when.apply, see JQuery document and What does $.when.apply($, someArray) do? for more details.

samabcde
  • 6,988
  • 2
  • 25
  • 41