Search code examples
javascriptgoogle-apps-scriptglobal-variablesgoogle-workspace-add-ons

Variable isn't being properly referenced across functions


I'm writing an Google Workspace add-on for Google Calendar, using Google Apps Script.

I'm having trouble getting different functions to reference the value of a variable

  1. I have a startDate variable defined at the root set to "today"
  2. In createDate it gets set to "tomorrow"
  3. It then displays it correctly in a card header as "Default start tomorrow"
  4. When you click on the button, reviseStartDate is called
  5. A new card is created, and it's header incorrectly says "Revised start today" instead of "Revised start tomorrow"

Here is my code, you can run it as-is:

var startdate = "today"; // Define startdate as a global variable with an initial value

function onOpen() {
 var card = createCard();
  return card;
}

function createCard() {
  startdate = "tomororw"; // Update the value of startdate
  var button = CardService.newTextButton()
    .setText('Revise start date')
    .setOnClickAction(CardService.newAction()
    .setFunctionName('reviseStartDate'));

  var section = CardService.newCardSection()
    .addWidget(button);

  var card = CardService.newCardBuilder()
    .setHeader(CardService.newCardHeader().setTitle('Default start:' + startdate))
    .addSection(section)

  return card.build();
}

function reviseStartDate() {
  var card = CardService.newCardBuilder()
    .setHeader(CardService.newCardHeader().setTitle("Revised start:" +startdate));

  return card.build();
}
  

And here is part of my manifest

  "calendar": {
  "homepageTrigger": {
    "runFunction": "onOpen"
  },
  "eventOpenTrigger": {
    "runFunction": "showFreeTime"
  }

How can I allow start date to be read and written by multiple functions, in "regular" javascript this would work fine. Thanks

Google add-ons docmentation

Google Apps Script reference


Solution

  • Google Apps Script handles these variables differently, they are evaluated in every execution and calling the script to create a card is considered a separate execution:

    1. Script runs to create a card, this card is now displayed in the side bar but that doesn't mean that the script is still executing, GAS already completed the requested operation which was creating a card.
    2. Using the UI in the already created card runs the reviseStartDate() function but that is considered a new and separate execution (as shown in the execution log) meaning that the variables are re-evaluated.

    I found this post that explained a similar behavior and found a workaround that involved using the CacheService to store your variables, this modification would yield the desired output:

    var cache = CacheService.getUserCache();
    
    
    function onHomepage() {
      var card = createCard();
      return card;
    }
    
    function createCard() {
    
      cache.put("startdate","tomorrow");
      var startdate = cache.get("startdate");
    
      var button = CardService.newTextButton()
        .setText('Revise start date')
        .setOnClickAction(CardService.newAction()
          .setFunctionName('reviseStartDate'));
    
      var section = CardService.newCardSection()
        .addWidget(button);
    
      var card = CardService.newCardBuilder()
        .setHeader(CardService.newCardHeader().setTitle('Default start: ' + startdate))
        .addSection(section)
    
      return card.build();
    }
    
    function reviseStartDate() {
    
      var startdate = cache.get("startdate");
    
      var card = CardService.newCardBuilder()
        .setHeader(CardService.newCardHeader().setTitle("Revised start: " + startdate));
    
      return card.build();
    }
    

    Another alternative would be to use User Properties that work in a similar fashion.


    Some Docs: