Tiffany G. Wilson Tiffany G. Wilson - 4 months ago 36
HTML Question

Success handler in Google Apps script receives null from server function

I am trying to display data from a server function in a Google Sheets sidebar. I am using an asynchronous call to the server with a success handler, but the client somehow receives a null value. Despite extensive searching on client-server communication I haven't been able to figure out why.

Currently, the log at the end of the server function shows the object 'flags' fully defined, but the console log at the beginning of the successHandler 'showErrors' says that 'flags' is undefined.

I checked the Google documentation on the HTML service, and as far as I can tell 'flags' is a valid return value since it is an object containing integers, strings, and an array of strings. I tried changing 'flags' from an object so a simple string, and it's still undefined in 'showErrors.' Does anybody know why the content of 'flags' is getting lost between the server and the client? Thanks in advance!

HTML:



<form onsubmit="google.script.host.close()">

<div id="intro" style="font-style:italic">
<p><b>Title</b><br><br>
Introduction text</p>
<HR>
<input type="button" style="button" id="start" value="Start" onclick="hideDiv('intro');google.script.run.withSuccessHandler(showErrors).checkList2(0,0)"> <!-- Intro starts loop -->
</div>

<div id="showErrors"></div>
</form>

<script>
function showErrors(flags){
console.log('client side flags:');
console.log(flags);
var div = document.getElementById('showErrors');
div.innerHTML = '<p style="font-style:italic">';
div.innerHTML += 'Sheet '+flags.pageNum+' of '+flags.numPages+'.';

//... more div.innerHTML += ...

div.innerHTML += '<input type="button" style="button" value="Next" onclick="google.script.run.withSuccessHandler(showErrors).checkList2('+Number(flags.pageNum)+1+','+flags.totalErrors+')"';
div.innerHTML += '<input type="submit" style="button" value="Cancel">';
}

function hideDiv(div){
document.getElementById(div).innerHTML=''; // clear div
}
</script>





Server function:



function checkList2(nComplete,nErrors){

var nSheets=21;
nComplete = Number(nComplete);
nErrors = Number(nErrors);

var results = errorList(nComplete); // Get results.name (string) and results.errors (array)
var errors = results.errors;
if (errors=='') {
checkList2(nComplete+1,nErrors); // Move on to next sheet
} else {
nErrors = nErrors + errors.length;

var flags = {};
flags.numErrors = errors.length;
flags.totalErrors = nErrors;
flags.pageNum = nComplete;
flags.numPages = nSheets;
flags.sheetName = results.name;
flags.errors = errors;
Logger.log('server side flags:')
Logger.log(flags)

return flags;
}
}




Answer

You don't return anything to the client if you enter this if block:

if (errors=='') {
  checkList2(nComplete+1,nErrors); // Move on to next sheet

  // no return
} else {
  nErrors = nErrors + errors.length;       

  var flags = {};
  flags.numErrors = errors.length;
  flags.totalErrors = nErrors;
  flags.pageNum = nComplete;
  flags.numPages = nSheets;
  flags.sheetName = results.name;
  flags.errors = errors;
  Logger.log('server side flags:')
  Logger.log(flags)

  return flags;
}

All you need to do is return the recursive call, and I think you'll get the behavior you're expecting.

if (errors=='') {
  return checkList2(nComplete+1,nErrors); // Move on to next sheet
} else {
  nErrors = nErrors + errors.length;       

  var flags = {};
  flags.numErrors = errors.length;
  flags.totalErrors = nErrors;
  flags.pageNum = nComplete;
  flags.numPages = nSheets;
  flags.sheetName = results.name;
  flags.errors = errors;
  Logger.log('server side flags:')
  Logger.log(flags)

  return flags;
}