Passing data to html service

One of the challenges when using htmlService is passing data from the server to client. Let's look at an example.
Consider this -

the script
function doGet(e) {
   return HtmlService
      .createTemplateFromFile('mytemplate')
      .evaluate();
}

function getValue() {
  return 'hello world';
}

the template
<script>
  google.script.run.withSuccessHandler(function (value) {
    alert (value);
  } ).getValue();
</script>

I get a correct hello world alert.

So now let's try amending the script like this
var global = "hello world";
function doGet(e) {
   return HtmlService
      .createTemplateFromFile('mytemplate')
      .evaluate();
}

function getValue() {
  return global;
}

It still works.

How about this.
var global;
function doGet(e) {
   global = "hello world";
   return HtmlService
      .createTemplateFromFile('mytemplate')
      .evaluate();
}

function getValue() {
  return global;
}

This time I get undefined instead of 'hello world'.

What's going on ?

When you execute google.script.run() on the server, it initiatializes the script again. This means that any global variables are reinitialized each time. In other words - a global variable only retains its value inside the instantiation of its script. In the first case the same value would have been set as before - since it's outside any function and would have been re-executed. In the second case, doGet() would have needed to be executed to give the variable a value. Since it is not, the variable remains as undefined.

This makes it fairly tricky to do things like pass parameters received by doGet(e) to a script running on the client side. Approaches to this might be to use the propertyService, or perhaps the cacheService for when the call from google.script.run comes.

In some cases though, it's not necessary. Here's the approach I use (which avoids the call back to the server from the client script altogether).

My script

function doGet(e) {
   var data  = {text:"hello world"};
   
   // get the template
   var html = HtmlService
      .createTemplateFromFile('mytemplate')
      .evaluate()
      .getContent();
   
   // now pass the data via a script
   return HtmlService
     .createTemplate(html +    
       "<script>\n" + 
        "doIt( " +
          JSON.stringify(data) +
        ");\n</script>")
        .evaluate();
}

My template

<script>
function doIt(data) {
  alert (data.text);
}
</script>

Using this method, we don't need any global variables that would need reinitializing, because we evaluate a template that already contains the embedded variable data from the main script.

Explanation

Here's the data we need to get to the client side script.

var data  = {text:"hello world"};


The client script wants to do something with it - so we wrap the scripted actions in a function that expects its data as an argument.

<script>
function doIt(data) {
  alert (data.text);
}
</script>

Evaluate that template as normal, but get its content
   // get the template
   var html = HtmlService
      .createTemplateFromFile('mytemplate')
      .evaluate()
      .getContent();

Append the data right in your evaluated template, and include a call to the script that does the work. The data will actually be written as part of the script, then evaluate the whole thing.

   // now pass the data via a script
   return HtmlService
     .createTemplate(html +    
       "<script>\n" + 
        "doIt( " +
          JSON.stringify(data) +
        ");\n</script>")
        .evaluate();

Here's what the overall evaluated script that HtmlService will finally execute, and why it works.

<script>
function doIt(data) {
  alert (data.text);
}
</script>

<script>
doIt( {"text":"hello world"});
</script>

See Google Apps Scripts snippets for more like this, or Getting an htmlservice template from a library for more on this topic. This technique is illustrated in Displaying analytics data on site pages. You can also find out about How to pass non stringifyable objects to html service here.

For help and more information join our forumfollow the blogfollow me on twitter

You want to learn Google Apps Script?

Learning Apps Script, (and transitioning from VBA) are covered comprehensively in my my book, Going Gas - from VBA to Apps script, available All formats are available now from O'Reilly,Amazon and all good bookshops. You can also read a preview on O'Reilly

If you prefer Video style learning I also have two courses available. also published by O'Reilly.
Google Apps Script for Developers and Google Apps Script for Beginners.




Comments