How to ajax call for data to expand table row for more information

In the ajax call below, the variable shtml is empty. What is the correct way to assign the value to the variable? If I return it inside the success function I get a “Uncaught TypeError: Cannot read property ‘show’ of undefined” error. row.child(moreinfo(row.data())).show();

function moreinfo(d) {
  var shtml = "";
  $.ajax({
    type: "GET",
    url: Url + parseInt(d[1]),
    contentType: "application/json",
    dataType: "json",
    success: function(data) {
      shtml = '<table" cellspacing="0" border="0"style="width: 100%;" >' +
        '<tr>' +
        '<td>Description:</td>' +
        '<td>' + data.description + '</td>' +
        '</tr>' +
        '</table>';

    },
    error: function(xhr, textStatus, errorThrown) {
      alert(errorThrown.responseText);

    }
  });
  return shtml;


}

$('#Ptable tbody').on('click', 'td.details-control', function() {
  var tr = $(this).closest('tr');
  var row = table.row(tr);
  if (row.child.isShown()) {
    // This row is open - close 
    row.child.hide();
    tr.removeClass('shown');
  } else {
    // Open this row
    row.child(moreinfo(row.data())).show();
    tr.addClass('shown');
  }
});

Answer

As you are working with ajax it will execute asynchronously. Thus on execution $.ajax(, it will not wait for response to come and go to next line which is return shtml; So, your shtml will always return "".

To solve your problem you can change your code as below.

  1. Update parameters in moreinfo as moreinfo(row, tr).
  2. Get d value inside moreinfo with let d = row.data();.
  3. Add row.child(shtml).show(); & tr.addClass('shown'); inside success callback from $.ajax.
  4. Call moreinfo(row, tr); from click.

// update function parameter
function moreinfo(row, tr) {
  // get data
  let d = row.data();

  $.ajax({
    type: "GET",
    url: Url + parseInt(d[1]),
    contentType: "application/json",
    dataType: "json",
    success: function(data) {
      var shtml = '<table" cellspacing="0" border="0"style="width: 100%;" >' +
        '<tr>' +
        '<td>Description:</td>' +
        '<td>' + data.description + '</td>' +
        '</tr>' +
        '</table>';

      // Open this row
      // Add html to child
      row.child(shtml).show();
      tr.addClass('shown');

    },
    error: function(xhr, textStatus, errorThrown) {
      alert(errorThrown.responseText);

    }
  });
}

$('#Ptable tbody').on('click', 'td.details-control', function() {
  var tr = $(this).closest('tr');
  var row = table.row(tr);
  if (row.child.isShown()) {
    // This row is open - close 
    row.child.hide();
    tr.removeClass('shown');
  } else {
    // Open this row
    moreinfo(row, tr);
  }
});