0

for the first iteration of this it works fine, the table is created as intended. However upon the second iteration, the drop down menu is empty. The loops are all working correctly so I'm assuming it has to be something to do with how I am appending the option to select. Appreciate any help.

Javascript

function loadPlayers() {

  //first ajax call to retrieve players
  $.ajax({
    url: '/players',
    type: 'GET',
    contentType: "application/json",
    success: function(data) {

      //second ajax call to retrieve presentations
      $.ajax({
        url: '/presentations',
        type: 'GET',
        contentType: "application/json",
        success: function(presentationData) {

          // loop through each player and append player/presentation to table
          data.forEach(function(player) {
            console.log("players")
            $(".player-table").append(
              $('<tr>').append(
                $('<td>').attr('class', 'player-td').append(player.name),
                $('<td>').attr('class', 'presentation-td').append(player.presentation),
                $('<td>').attr('class', 'new-presentation-td').append(
                  $('<select>').attr('class', 'new-presentation-dropdown').append(

                    // loop through each presentation in database and add to dropdown
                    presentationData.forEach(function(presentation) {
                      console.log(presentation.name);
                      $(".new-presentation-dropdown").append('<option>' + presentation.name + '</option>')

                    })
                  )
                )
              )
            )
          })
        }
      })
    }
  })
}

HTML

  <table class="player-table">
    <tr class="player-name-tr">
      <th>Player Name</th>
      <th>Current Presentation</th>
      <th>New Presentation</th>
    </tr>
  </table>
dellboyant
  • 27
  • 8
  • Please look at this link. Your problem is async http://stackoverflow.com/questions/23283276/execute-function-after-ajax-call-is-complete/23283596#23283596 . You should write your second ajax within the .complete() – Naveen Chandra Tiwari Jul 01 '16 at 11:07
  • Try to reference the select you create and append the options to the reference. The selector $(".new-presentation-dropdown") has 1 more element for each iteration, might break the thing here. – Memme Jul 01 '16 at 11:14
  • @Memme that was my thinking, but I can't figure out another way to reference the select that works... – dellboyant Jul 01 '16 at 11:17
  • Anser below exposed exactly what I meant :-) – Memme Jul 01 '16 at 12:54

2 Answers2

1

You're running the 2nd loop inside the append statement - it means the loop appending the options is run before the <select> is created. Since the select element has not yet been created $(".new-presentation-dropdown") matches nothing in the DOM. Moving the loop appending the options outside of all the .append() statements should fix this issue:

data.forEach(function(player) {
    console.log("players");
    $(".player-table").append(
            $('<tr>').append(
                    $('<td>').attr('class', 'player-td').append(player.name),
                    $('<td>').attr('class', 'presentation-td').append(player.presentation),
                    $('<td>').attr('class', 'new-presentation-td').append(
                            $('<select>').attr('class', 'new-presentation-dropdown')
                    )
            )
    );

    // loop through each presentation in database and add to dropdown
    presentationData.forEach(function (presentation) {
        console.log(presentation.name);
        $(".new-presentation-dropdown").append('<option>' + presentation.name + '</option>')
    })
});

However $(".new-presentation-dropdown") will match every <select> created so that'll give strange results. I'd suggest you assign the $('<select>') to a variable and append the options to the variable, before appending it to the table, like this: (Untested but should work)

data.forEach(function(player) {
    console.log("players");

    var $newPresentationDopdown = $('<select>').attr('class', 'new-presentation-dropdown');

    // loop through each presentation in database and add to dropdown
    presentationData.forEach(function (presentation) {
        console.log(presentation.name);
        $newPresentationDopdown.append('<option>' + presentation.name + '</option>')
    });

    $(".player-table").append(
            $('<tr>').append(
                    $('<td>').attr('class', 'player-td').append(player.name),
                    $('<td>').attr('class', 'presentation-td').append(player.presentation),
                    $('<td>').attr('class', 'new-presentation-td').append($newPresentationDopdown)
            )
    );
});
Johan Palmfjord
  • 671
  • 4
  • 15
  • Ah thank you for the explanation, all makes sense now and is working as intended. Many thanks! – dellboyant Jul 01 '16 at 11:36
  • To avoid some overhead you could create the select outside the 1st loop, that way you only iterate it once (since it looks like the presentationData is the same for every player?) and just append it for each player. – Memme Jul 01 '16 at 12:51
0

Based on append method documentation you can pass function by below feature:

A function that returns an HTML string, DOM element(s), text node(s), or jQuery object to insert at the end of each element in the set of matched elements. Receives the index position of the element in the set and the old HTML value of the element as arguments. Within the function, this refers to the current element in the set.

Whiles below code is inconsistent by that rule:

$('<select>').attr('class', 'new-presentation-dropdown').append(

   // loop through each presentation in database and add to dropdown
     presentationData.forEach(function(presentation) {
         console.log(presentation.name);
         $(".new-presentation-dropdown").append('<option>' + presentation.name + '</option>')

    })
  )

You don't return any result in your passed function.