-1

This is not the same than Object property values lost on server side when object passed via google.script.run

I'm trying to set my Google Apps Script add-on test framework. Since Test as add-on can't be used to test installable triggers, I'm wondering if I could pull server side code from a bounded project to be use as a library to test my sidebars that call server-side functions.

If I run the below code using Run > Test as add-on... it shows my menu two times

  1. As a custom menu named "Sidebar", next to the Help menu
  2. As an add-on menu, on Add-ons > My Project
  • When I click on Sidebar > Open, clicking on the sidebar buttons getMail() returns undefined
  • When I click on Add-on > My Project > Open, clicking on the sidebar buttons getMail(), as expected, returns the active user email address.

The same happens, server side object lost, when I replace the getMail() function by another that use the Spreadsheet Service to return a cell value or even by one that return a primitive string.

What am I missing?

The bottom line is that I want to add a button on my sidebar that creates an installable trigger and get some values from the spreadsheet.

Spreadsheet to be used as library

Code.gs

function onOpen(e) {
  var ui = SpreadsheetApp.getUi();
  var menu = ui.createMenu('Sidebar');
  menu
    .addItem('Open', 'showSidebar')
    .addToUi();
}

function showSidebar() {
  var ui = HtmlService.createHtmlOutputFromFile('Sidebar')
    .setSandboxMode(HtmlService.SandboxMode.IFRAME)
    .setTitle('A Sidebar');
  SpreadsheetApp.getUi().showSidebar(ui);

}

function getEmail() {
  return Session.getActiveUser().getEmail();
}

Sidebar.html

<!DOCTYPE html>
<html>

<head>
  <base target="_top">
  <script>
    function updateButton(email, button) {
      console.log(email);
      button.value = 'Clicked by ' + email;
    }
  </script>
</head>

<body>
  <input type="button" value="Not Clicked" onclick="google.script.run
          .withSuccessHandler(updateButton)
          .withUserObject(this)
          .getEmail()" />
  <input type="button" value="Not Clicked" onclick="google.script.run
          .withSuccessHandler(updateButton)
          .withUserObject(this)
          .getEmail()" />
</body>

</html>

Examples of other functions used to replace getMail()

function getCellValue(){
  return SpreadsheetApp.getActiveCell().getValue();
}

function getGreeting(){
  return 'Hello world';
}

Spreadsheet to be used as library client

  1. Add the Library to the project
  2. Add the below code

    function onOpen(e) { aLib.onOpen(e); }

    function showSidebar(){ aLib.showSidebar(); }

    function getEmail(){ aLib.getEmail(); }

Test as add-on...

  1. Click on Run > Test as add-on
  2. Add "Spreadsheet to be used as library client " as doc to be used to test as add-on
  3. Launch the doc

Rubén
  • 34,714
  • 9
  • 70
  • 166
  • 1
    In my environment, unfortunately, your situation cannot be reproduced. I did as follows. 1. Create Spreadsheet and a bound script. 2. Put your scripts to the bound script. 3. Run > Test as add-on. But the opened spreadsheet has no "Sidebar" menu, only Add-on > My Project > Open. If I misunderstand your question, could you please tell me? By the way, how about using ``SpreadsheetApp.getUi().createAddonMenu().addItem('Open', 'showSidebar').addToUi()`` for adding the menu? – Tanaike May 30 '18 at 02:31
  • @Tanaike Testa as add-on requires to set a file, use the bounded spreadsheet for testing. I will add more details to question in a moment. – Rubén May 30 '18 at 02:42
  • @Tanaike I'm sorry. I just realized that I missing some details. It will take more time than I thought to update my question. – Rubén May 30 '18 at 02:51
  • Thank you for replying. No problem. – Tanaike May 30 '18 at 02:55

1 Answers1

0

According to https://developers.google.com/apps-script/guides/html/communication#private_functions google.script can't access library functions but it looks that it also can't access library objects.

The solution is to use global variables

Spreadsheet to be used as library

Code.gs

/* For tests only, assign the server side function
 * to be called from the sidebar to a global variable 
 */
var email = getEmail(); 

/**
 * Reference: https://stackoverflow.com/q/50595103/1595451
 *
 */
function onOpen(e) {
  var ui = SpreadsheetApp.getUi();
  var menu = ui.createMenu('Sidebar');
  menu
    .addItem('Open', 'showSidebar')
    .addToUi();
}

function showSidebar() {
  var ui = HtmlService.createHtmlOutputFromFile('Sidebar')
    .setSandboxMode(HtmlService.SandboxMode.IFRAME)
    .setTitle('A Sidebar');
  SpreadsheetApp.getUi().showSidebar(ui);

}

function getEmail() {
  return Session.getActiveUser().getEmail();
}

Spreadsheet to be used as library client

Code.gs

var email = aLib.email;

function onOpen(e) {
  aLib.onOpen(e);
}

function showSidebar(){
  aLib.showSidebar();
}

function getEmail(){
  /* Instead of calling the library function we call the library global variable */
  return email; 
}
Rubén
  • 34,714
  • 9
  • 70
  • 166