4

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;
  }     
}

6
  • Seems like it should all work. The only place I think you might have issues is the call to the errorList function. So it might be a good idea to check if passing a zero to that function causes an error. Commented Jul 30, 2016 at 22:02
  • @Dimu-Designs, errorList works just fine, in fact the first time it is called the argument is zero and it returns values the way it is supposed to. I don't understand how flags can be defined in Logger.log(flags) in the server function and undefined in console.log(flags) in the client side function. Don't they execute one right after the other? Commented Jul 31, 2016 at 0:38
  • Sorry, you're having to deal with this kind of bug. I only have a few ideas: What happens when you return something at the top of checkList2? Also, do you by chance have two functions named checkList2? Commented Jul 31, 2016 at 1:47
  • Try converting the object named flags to a string before returning it: flags = JSON.stringify(flags); Then parse the string in the success handler. flags = JSON.parse(flags); Commented Jul 31, 2016 at 2:53
  • @JoshDawson there is only one function checkList2. I tried returning a value at the beginning of the function and it is defined on the client side. I then tried moving the return down one line at a time to see where the error was. There is an if condition between var errors= and nErrors= that I omitted above since I didn't think it was relevant, but it's now included above. The return value is defined before this if and undefined after. Any thoughts? Commented Jul 31, 2016 at 3:13

1 Answer 1

2

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;
}
Sign up to request clarification or add additional context in comments.

1 Comment

THANK YOU! It makes complete sense now that you say it. I'm new at this, so I'm still learning the basics.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.