I'm using a library to keep the code resources synchronized accross 50+ spreadsheets. Each spreadsheet has a containter-bound script file that references the library as "Library.[something]".
The Library contains this code:
function userOpened() {
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.createMenu('Expenses')
.addItem('Expense Submission', 'expenseSubmittal_Local')
.addToUi();
}
function expenseSubmittal_Library() {
var html = HtmlService.createHtmlOutputFromFile('libraryTest')
.setWidth(400)
.setHeight(300);
SpreadsheetApp.getUi().showModalDialog(html, 'Expense Submittal');
}
function returnData_Library(){
return "my data";
}
and this html file called "libraryTest.html":
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div id="output">initializing...</div>
<script>
google.script.run.withSuccessHandler(function (data) {
var div = document.getElementById('output');
div.innerHTML = data;
}).returnData_Local();
</script>
</body>
</html>
The local container-bound code is as follows:
function userOnOpen(event) {
Library.userOpened();
}
function expenseSubmittal_Local(){
this.Library.expenseSubmittal_Library.apply(this);
}
function returnData_Local() {
return this.Library.returnData_Library.apply(this);
}
So when the spreadsheet is opened, an installed trigger runs userOnOpen to add a menu item that will trigger expenseSubmittal_Local when selected. That function then reference the Library to initialize a dialogue box containing the html file located in the library.
google.script.run is used within the html file to pull data that will be inserted into the html file (this data is simplified for this example). That data is returned from returnData_Local which pulls from returnData_Library.
When loaded successfully, the dialogue box should switch from "initializing..." to "my data". Unfortunately the dialogue box gets stuck on the "initializing..." and never switches to "my data". No errors are thrown in the browser console, but I do get an error in the Logger stating "Script function not found: returnData_Local".
In the html file, if I switch out
google.script.run.withSuccessHandler(function (data) {
var div = document.getElementById('output');
div.innerHTML = data;
}).returnData_Local();
for
google.script.run.withSuccessHandler(function (data) {
var div = document.getElementById('output');
div.innerHTML = data;
}).returnData_Library();
then the browser console WILL throw an error stating "google.script.run.withSuccessHandler(...).returnData_Library is not a function" So I can't seem to win either way.
All of this works if I move the html file and all the functions into the local container-bound script and ditch the library, but that's not the goal here.
How can I use google.script.run from an html file within a library??
Thanks!
UPDATE: I have found that changing the function names returnData_Local() and returnData_Library() so that they are the same name in both the container and the library to returnData() resolves the issue of the missing function error. I also find that the local container version of returnData() does absolutely nothing. It just needs to exist for google.script.run to not throw an error. For example:
The updated Library code:
function userOpened() {
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.createMenu('Expenses')
.addItem('Expense Submission', 'expenseSubmittal_Local')
.addToUi();
}
function expenseSubmittal_Library() {
var html = HtmlService.createHtmlOutputFromFile('libraryTest')
.setWidth(400)
.setHeight(300);
SpreadsheetApp.getUi().showModalDialog(html, 'Expense Submittal');
}
function returnData(){return "my data"}
The updated html in the Library:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div id="output">initializing...</div>
<script>
google.script.run.withSuccessHandler(function (data) {
var div = document.getElementById('output');
div.innerHTML = data;
}).returnData();
</script>
</body>
</html>
The updated local container-bound code is as follows:
function userOnOpen(event) {
Library.userOpened();
}
function expenseSubmittal_Local(){
this.Library.expenseSubmittal_Library.apply(this);
}
function returnData() {}
It seems really strange to me that the local container needs to contain the same function name even though it doesn't run. But then again maybe I don't understand the scope correctly. Also, it takes about 5 seconds for the html to get populated with "my data" which seems exorbitant for such a simple function. Maybe it's lagged due to the fact that I'm using a library, but I've never seen the library have that much of a delay impact on any other part of my app. When I run the html locally in the container, "my data" populates pretty much instantly...