Google Script HTML form from Library throws error Uncaught
I have a library with HTML-form like this:
code.gs
:
function openDialog() {
SpreadsheetApp.getUi().showModalDialog(HtmlService.createHtmlOutputFromFile("h"), "Test" );
}
function hello() {
console.log('booo');
}
h.html
:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<button id="b">Click me</button>
<script>
var b = document.getElementById('b');
b.onclick = function() {
google.script.run
.withSuccessHandler(function(str){window.alert("executed");})
// .withFailureHandler(function(error){window.alert("failed");})
.hello();
}
</script>
</body>
</html>
I shared this script for view and deployd it as a library. Next I created a bound script in Google Sheet with this code:
function onOpen() {
SpreadsheetApp.getUi().createMenu('test').addItem('run', 'myFunction').addToUi();
}
var hello = function() {};
function myFunction() {
TT.openDialog();
}
I've added the library with identifier: TT.
Next I refreshed my Google Sheet file with bound code to see the menu "test", ran test > run. The HTML-window appeared. When I clicked the button, nothing happened. When I opened console, I saw the error:
This error does not appear if I do not use library.
Please help me to resolve this.
Solution 1:
I have experienced the same situation with you. In my case, the reason of the issue was due to the authorization at the library side.
- When the authorization process for using the scopes in the library is NOT done at the library side, I confirmed that the error of
Uncaught
occurred. - When the authorization process for using the scopes in the library is done at the library side, I confirmed that the error of
Uncaught
didn't occur.
Namely, in my environment, I confirmed that when the library is used for your situation, it was required to authorize the scopes for both the client side and the library side.
So, as a workaround, I used the following flow.
Workaround:
- Create a Google Apps Script library.
- Please copy and paste your script of
code.gs
andh.html
to the standalone script or the container-bound script.
- Please copy and paste your script of
- Deploy the Google Apps Script as the library.
- In your script, for example, please directly run
hello()
at the library side, and authorize the scopes. - Install the library to the client side and load the library from the client side.
- Please run
myFunction()
at the client side.
By this flow, when you run run
at the custom menu and click the button, the dialog of executed
is opened.
Note:
- In this case, when I wanted to make users use the client script, it was required to authorize the scopes for both the client side and the library side. I thought that this may be a little inconvenient.
- So, how about reporting this for the Google issue tracker? Ref Unfortunately, I couldn't find the issue tracker with the same situation.
Added:
As the method for authorizing the scopes at the library side from the client side, I would like to propose to use Web Apps. I thought that when the Web Apps is used, the authorization of the library side can be done at the client side. By this, I thought that the inconvenience may be resolved a little.
Please do the following flow.
1. Library side.
Please copy and paste the following scripts.
Google Apps Script: code.gs
function openDialog() {
SpreadsheetApp.getUi().showModalDialog(HtmlService.createHtmlOutputFromFile("h"), "Test" );
}
function hello() {
console.log('booo');
}
function doGet() {
return HtmlService.createHtmlOutput("ok");
}
HTML: h.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<button id="b">Click me</button>
<script>
var b = document.getElementById('b');
b.onclick = function() {
google.script.run
.withSuccessHandler(function(str){window.alert("executed");})
// .withFailureHandler(function(error){window.alert("failed");})
.hello();
}
</script>
</body>
</html>
2. Deploy Web Apps at library side.
Please deploy Web Apps at the library side. About the method for this, you can see the official document. Ref The detail setting is as follows.
Execute as: User accessing the web app
Who has access: Anyone with Google account
3. Deploy as library.
Please deploy as the library. Ref
4. Client side.
Please install the library to the client side. And, please copy and paste the following scripts. In this case, please replace https://script.google.com/macros/s/###/exec
with your Web Apps URL.
function onOpen() {
SpreadsheetApp.getUi().createMenu('test').addItem('auth', 'auth').addItem('run', 'myFunction').addToUi();
}
var hello = function() {};
function myFunction() {
TT.openDialog();
}
function auth() {
const html = HtmlService.createHtmlOutput(`<input type="button" value="Authorize" onclick="window.open('https://script.google.com/macros/s/###/exec', '_blank');google.script.host.close()">`);
SpreadsheetApp.getUi().showDialog(html);
}
5. Testing.
At first, please run auth
at the custom menu. By this, you can authorize the scopes of both the client side and the library side. When the new tab is not opened when auth
is run, please run auth()
at the script editor again.
As the next step, please run run
. By this, your dialog is opened. And, when both authorizations (client and library side) with auth
has already been finished, when you click the button, the dialog of executed
is opened.
References:
- Web Apps
- Taking advantage of Web Apps with Google Apps Script