Skip to content

ToggleButton for Google HtmlService

What is the easiest way to get some kind of toggle switch for Google HtmlService?

Google UiApp used to be able to create a simple ToggleButton like the following:

var toggleButton = app.createToggleButton('ON', 'Off').setId('MySwitch');

But UiApp has been deprecated. “Please use HtmlService instead”

I’ve tried

But found I cannot make them a two-stage item. Then I tried

and was able to get the HTML part working, but moving it to Google HtmlService, I cannot make it work no matter what.

Can someone give me a working Google HtmlService example that contains a two-stage item that I can use to control my output please.


Thanks a lot @MetaMan for your excellent example, I tried hard to come up with the smallest example, but I’ll never be able to get the level of your code, so compact and elegant!

Just one thing, I haven’t been able to make it work yet. I’m getting ReferenceError: gobj is not defined.

enter image description here

I then changed them into plain text, as

enter image description here

But got Execution completed without seeing the dialog. How can I make it works?


Ops, dialog showed up after a while. Thanks @MetaMan, I’ll ask the following in a separated question —

One more thing, @MetaMan, In the HTML demo code that I provided, I was able to make use of form.myButton.value, but the problem is when I try to use that to update my label from within Google App Code function, just as what the HTML demo code is doning, it always fails and I don’t know why. Do you have a quick answer for that, or you’d rather me asking in a separated question?



Here’s a toggle function that presents a dialog that has a button that turns a light on and off:

function launchLightToggleDialog() {
  let html='';
  html += '<html><head></head><body>';
  html += '<br /><img id="light" src="" />';
  html += '<br /><input type="button" id="btn" value="Toggle" onclick="toggle()" />&nbsp;&nbsp;<label id="lbl" for="btn"></label>';
  html += '<script>';
  html += 'var light="on";'  
  html += 'var lighton = <?= getMyDataURI(gobj.globals.lightonid) ?>;n';
  html += 'var lightoff = <?= getMyDataURI(gobj.globals.lightoffid) ?>;n';
  html += 'window.onload=function(){document.getElementById("light").src=(light=="on")?lighton:lightoff;document.getElementById("lbl").innerHTML=light;}n';

  html += 'function toggle(){light = (light=="on")?"off":"on";document.getElementById("light").src=(light=="on")?lighton:lightoff;document.getElementById("lbl").innerHTML=light;}n';
  html += 'console.log("mycode");n'
  html += '</script>';
  html += '</body></html>';
  let t=HtmlService.createTemplate(html);
  let o=t.evaluate();//The dataURI's get loaded here
  SpreadsheetApp.getUi().showModelessDialog(o,"Light Toggle");

The below function just opens up the files where I store the dataURI’s of the lighton and lightoff images and it returns the dataURI’s as strings for use in the webapp. Making it possible for me to serve the images off of my Google Drive.

function getMyDataURI(fileId) {
  const file=DriveApp.getFileById(fileId);
  return file.getBlob().getDataAsString();


enter image description here

Both functions are Google Apps Script and all JavaScript functions are imbedded in the html string.

If you wish to convert an image to a dataURI:

function convImageUrl(url){
  var url=url || "default url";
  var blob=UrlFetchApp.fetch(url).getBlob();
  var b64Url='data:' + blob.getContentType() + ';base64,' + Utilities.base64Encode(blob.getBytes());
  return b64Url;

function saveDataURIInFile(filename,datauri,type) {
  Logger.log('filename: %sndatauri: %sntype: %sn',filename,datauri,type);
  if(filename && datauri && type) {
    var folder=DriveApp.getFolderById(getGlobal('MediaFolderId'));
    var files=folder.getFilesByName(filename);
    while(files.hasNext()) {;
    var f=folder.createFile(filename,datauri,MimeType.PLAIN_TEXT);
    return {name:f.getName(),id:f.getId(),type:type,uri:DriveApp.getFileById(f.getId()).getBlob().getDataAsString()};
    throw('Invalid input in saveDataURIInFile.');