0
votes

I have a google apps-script add-on which is loaded in the side bar of a Google Spreadsheet.

How does one reload an apps script add-on ones the user switches sheets or from button click ?

1

1 Answers

2
votes

The simplest way to reload an ad-on is to start/launch it again from the add-on's menu - this will re-load the sidebar. Or you can add a button to your sidebar which runs google.script.run.showSidebar() (or whatever your server-side function for showing the sidebar is called).

Since add-ons only have access to simple triggers (onInstall(), onOpen() and onEdit()) and can't (yet) tell what a user does outside the add-on, you will have to write your own javascript function in the sidebar's html page to re-set the your add-on's user interface to default state (I assume that is what you mean by "reload"), i.e to reset all form fields to default values, remove any injected help/status text, etc etc.

To have this function execute on button click is not too hard - just trigger the function from the button's onclick event. With a bit more work you can even add a 'Reset' menu item in your add-on's menu that does the same thing.

To make such function run 'automatically' when user switches sheet is also possible, but will require polling for spreadsheet changes. Basically you can write a javascript function in your add-on's sidebar page that runs on a certain interval and calls a server-side function that checks if currently active sheet is same as before (which you can store in userProperties, for example). If the sheet is different, call your js function that resets the ui of your add-on + update the userProperty with the name of currently active sheet. Keep in mind that there will be a bit of delay between user switching sheets and your add-on running its reset code and reloading its ui - if that is an issue, then reloading the ui from button click is a better option.

Here is some sample code to give you an idea of what you can do. You can view the working spreadsheet here

Code.gs

function onOpen(e) {
  // Add this add-on to Add-ons menu
  SpreadsheetApp.getUi().createAddonMenu()
      .addItem('Start / Reset', 'showSidebar')
      .addToUi();

  // save current active sheet name in user properties for later checking if user switched sheets
  saveSheetNameToProperty();
};

function onInstall(e) {
  onOpen(e);
};

function showSidebar() {
  var ui = HtmlService.createHtmlOutputFromFile('Sidebar').setTitle('Add-on Reset Test');
  SpreadsheetApp.getUi().showSidebar(ui);
};

/**
 * Saves current active sheet name to user property lastActiveSheet
 * @param String sheetname Name of sheet to save to user property. If undefined (not passed), saves current active sheet name.
 */
function saveSheetNameToProperty(sheetname) {
  var sheetName = sheetname || SpreadsheetApp.getActiveSheet().getName();
  PropertiesService.getUserProperties().setProperty("lastActiveSheet", sheetName)
};

/**
 * Checks if user has switched sheets by comparing current active sheet name to name stored in user property
 * @return Boolean True/False flag denoting if sheet was switched. True=sheet was switched; False=still on same sheet
 */
function checkSheetChanged() {
  var sheetChanged = false;
  var sheetName = SpreadsheetApp.getActiveSheet().getName();
  var lastActiveSheet = PropertiesService.getUserProperties().getProperty("lastActiveSheet");
  if (sheetName!=lastActiveSheet) {
    sheetChanged = true;
    saveSheetNameToProperty(sheetName);
    // if you'd rather just reload the whole sidebar, then un-comment the line below and delete the return statement
    // showSidebar();
  }
  return sheetChanged;
};

Sidebar.html

<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
<!-- The CSS package above applies Google styling to buttons and other elements. -->

<div class="sidebar branding-below">
  <form id="addonForm">
    <div class="block">
      <label for="selectBox">Select a value:</label>
      <select name="selectBox" id="selectBox">
        <option value="" selected>Select a value...</option>
        <option value="Value 1">Value 1</option>
        <option value="Value 2">Value 2</option>
        <option value="Value 3">Value 3</option>
      </select>
    </div>
    <div class="block">
      <label for="textBox">Enter some text:</label>
      <input type="text" name="textBox" id="textBox" placeholder="Enter some text...">
    </div>
    <div class="block" id="button-bar">
      <button type="button" class="blue" id="simpleResetBtn" onclick="resetForm(true);" title="I reset the sidebar's form controls to their default state">Reset form</button>
      <button type="button" class="red" id="reloadAddonBtn" onclick="google.script.run.showSidebar();" title="I completely reload the sidebar - fresh start!">Reload add-on</button>
    </div>
  </form>
  <div class="block" id="statusText" style="color:#666; margin-top:10px;"></div>
</div>

<div class="sidebar bottom">
  <span class="gray branding-text">Reset Add-on Sample by Azadi</span>
</div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
/**
 * On document load, set up interval-based execution of checkSheetChanged() function to check if user has switched sheets
 */
$(function() {
  // run checkSheetChanged() function every 5000 miliseconds
  var sheetChecker = window.setInterval(checkSheetChanged, 5000);
});

/**
 * Resets the form in the add-on's sidebar and shows status text.
 * @param Boolean fromButtonClick Boolean flag denoting if form reset was triggered from button click or via timed script execution
 */
function resetForm(fromButtonClick) {
  var buttonClick = fromButtonClick || false;
  var form = $("#addonForm")[0];
  var statusDiv = $("#statusText");
  form.reset();
  if (buttonClick) {
    statusDiv.text("Addon UI has been reset from [Reset form] button click");
  }
  else {
    statusDiv.text("Addon UI has been reset automatically via timed script following sheet switch");
  }
};

/**
 * Runs the checkSheetChanged() server-side function (in Code.gs) to check if user has switched sheets
 * and executes checkSheetChangedCallback() function on success
 */
function checkSheetChanged() {
  google.script.run.withSuccessHandler(checkSheetChangedCallback).checkSheetChanged();
};

/**
 * Callback for checkSheetChanged() function.
 * Resets the form in the sidebar if user has switched sheets.
 * @param Boolean isDifferentSheet Boolean flag returned from server-side script. True=sheet was switched. False=user is still on same sheet.
 */
function checkSheetChangedCallback(isDifferentSheet) {
  if (isDifferentSheet) {
    resetForm();
  }
};
</script>

Hope this helps!