I have created a lot of apps using Apps Script and HTMLService for my work and all the apps have been working perfectly(reports,submission tools,trackers,etc) however, since Feb 25th,2014 they are not working, not even a single one of them.
When I click the button of a html form in my app it should load another page but now I click on the link and nothing happen, I really need your help since I dont know why they are not working when they used to work without any inconvenient.
Below you can find a code that worked before and now is not working,
Code.gs
function doGet() {
var template= HtmlService.createTemplateFromFile('test');
template.action = ScriptApp.getService().getUrl();
return template.evaluate()
}
function doPost(e){
var template = HtmlService.createTemplateFromFile('test.html');
template.action = ScriptApp.getService().getUrl();
return template.evaluate();
}
test.html
<!DOCTYPE html>
<html>
<body>
Exception Tracker Report <br/><br/>
<form >
<input name = "test" value="test">
Test<input type="submit" value="Load" />
</form>
</body>
</html>
I really request your help in this matter since all the apps that I have created using HTMLService are not working (20 or more apps).
Once again, the code above should work without any problem but I dont know if there have been changes in the HTMLService Google class or anything regarding this.
Thanks for your help
Google made a change yesterday on htmlservice, by defect if not mentioned the sandbox mode was emulated. They changed it to native.
As it's not mentioned in your script, you where running in emulated mode and since yesterday ... it changed to native mode.
You need to specify in your script that you want to use the emulated mode.
this way:
function doGet() {
var template= HtmlService.createTemplateFromFile('test');
template.action = ScriptApp.getService().getUrl();
return template.evaluate().setSandboxMode(HtmlService.SandboxMode.EMULATED);
}
Related
I would like to have a google sheet that when you pick something on a google sheet it brings up an html file on a new google tab that has info from the google sheet. I am using the code below as a quick test to see if this is possible.
Right now I have a menu item that calls myFunction(), then I would like that to bring up the new html page. This doesn't come close to working, as it just enters and exits myFunction and no html page. So was wondering if anyone knows if this is possible. If so can you give me some hints on how to do it.
code.gs
function myFunction(){
HtmlService.createTemplate('page');
};
page.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<title>Hello<\title>
</body>
</html>
Change myFunction() to doGet(), and you need to return the HtmlService from the doGet function. Also, the statement inside the doGet() function is different than what you currently have.
Your myFunction() function should look like this
function doGet() {
return HtmlService.createTemplateFromFile('page').evaluate();
}
doGet() is a special function that Google Apps Script web app scripts should handle any GET requests.
For more information, please refer to one of these guides:
https://developers.google.com/apps-script/guides/html/templates
https://developers.google.com/apps-script/guides/html
This is absolutely possible.
What you want to implement is a web app.
Simple Example
function doGet() {
textOutput = ContentService.createTextOutput("Hello World! Welcome to the web app.")
return textOutput
}
Put this in a script file and then deploy the script as a web app - instructions. The deploy process will give you a link with which you can visit the web app and see your text output.
What apps script does is that every time someone visits the URL, the doGet function is run.
HTML Example
function doGet(){
let HTMLString = "<style> h1,p {font-family: 'Helvitica', 'Arial'}</style>"
+ "<h1>Hello World!</h1>"
+ "<p>Welcome to the Web App";
HTMLOutput = HtmlService.createHtmlOutput(HTMLString);
return HTMLOutput
}
As you have already seen, HtmlService is what to use to serve up HTML.
Linking to Spreadsheet
The best way IMO to approach this is:
Create a spreadsheet.
Create the script from the spreadsheet menu - this ensures that the script and sheet are linked.
Decide how you want to present the information from the Spreadsheet and get it with something like:
let file = SpreadsheetApp.getActive(); // getActive only possible if script and sheet are linked
let sheet = file.getSheetByName("Sheet1");
let range = sheet.getDataRange();
let values = range.getValues();
Figure out how to translate that into HTML.
Write your doGet function.
Deploy
Profit!
Docs
Google Apps Script Web Apps
HTML Service
Spreadsheet Service
I'm learning how to use Google Web App and am following this YouTube video Google Sheets Web App Example - Google Apps Script Web App Tutorial - Part 1 and I am really enjoying the series. It is very easy to follow along with the videos. But I am running into a little issue with the first video. For some reason when I try to do log the button click on the HTML page, nothing happens. I sure it's going to be something silly. But I have been at this now for a few hours and I can't figure out what is wrong.
Code.gs:
function doGet(e) {
Logger.log(e.parameter);
return HtmlService.createHtmlOutputFromFile("page");
}
function userClicked(name){
Logger.log(name + " & noah clicked it!");
}
page.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h1>Hello</h1>
<label>Name:</label><input type="text" id="username">
<button id="btn">Run It!</button>
<script>
document.getElementByID("btn").addEventListener("click",doStuff);
function doStuff(){
var uname document.getElementByID("username").value;
google.script.run.userClicked(uname);
}
</script>
</body>
</html>
Please tell me there is something silly that I am just not seeing.
I think that your script of HTML side is not correct. By this, the script is not run. So I think that Logger.log is not run. Please modify your script of HTML side as follows and test it again.
Modification points:
getElementByID is getElementById.
var uname document.getElementByID("username").value; is var uname = document.getElementById("username").value;.
Modified script:
From:
<script>
document.getElementByID("btn").addEventListener("click",doStuff);
function doStuff(){
var uname document.getElementByID("username").value;
google.script.run.userClicked(uname);
}
</script>
To:
<script>
document.getElementById("btn").addEventListener("click",doStuff); // Modified
function doStuff(){
var uname = document.getElementById("username").value; // Modified
google.script.run.userClicked(uname);
}
</script>
By this modification, you can see the log at Apps Script Dashboard.
IMPORTANT:
In your case, when you access to the Web Apps using your browser by logging in to your Google account, the log can be seen. But if you want to access to a script and curl, please include the access token to the request header. By this, the log can be seen. Please be careful this.
When you cannot include the access token to the request header, in that case, please link the Google Apps Script project to Google Cloud Platform (GCP) Project. By this, the log can be seen at Apps Script Dashboard.
References:
getElementById()
Apps Script Dashboard
Here is my code for show a sidebar. When click at OK button, I will insert a new record to my sheet.
It works well when I disable V8 by Run->Disable new App Script .. V8.
When I enable V8, onClicked in Code.gs not fired anymore.
I have checked the V8 Runtime Overview but I didn't find anything.
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<button onclick="okClicked()"> OK </button>
<button onclick="close()">Close </button>
<script>
function okClicked(){
window.alert("A");
google.script.run.okClicked();
}
function close(){
google.script.host.close();
}
</script>
</body>
</html>
Code.gs
function showSidebar() {
var html = HtmlService.createHtmlOutputFromFile('Index')
.setTitle('My custom sidebar')
.setWidth(300);
SpreadsheetApp.getUi().showSidebar(html);
}
function okClicked(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data");
sheet.appendRow(["A", "B"]);
}
Any help or suggestion would be great appreciated.
Someone posted an issue similar to createHtmlOutputFromFile and V8 on Google's Issue Tracker. You can check if this issue is adequate for your case and hit the Star to let them know you have the same issue.
If you believe that this issue does not correspond with yours, you can also create a new issue with your case there.
2021 Answer
FWIW, I found that Google Apps Script was erroring out like this when my partner and I were both logged into the same Google account.
We also found that this can happen when new features have been built into your Google Apps Script / Sheets backend code that require updated permissions that haven't been granted yet. It's a bit hacky, but I fixed this by:
Sharing the sheet with another account I own
Logging into that account, then trying to run the function
Agreeing to grant the permissions asked by Google Auth / Scopes in the dialog that follows
Say I have an HTML file with various inputs. According to these inputs I would like to send an email and then display a thank you message or redirect to a thank you page.
I am loading the index.html file in the doGet() as below:
function doGet(){
var template = HtmlService.createTemplateFromFile('index');
template.action = ScriptApp.getService().getUrl();
return template.evaluate();
}
After adding the implementation which I require in doPost(e) function, deploying the code into a web app, filling in the form and submitting, everything seems to be working perfectly apart from the last bit. I want to show an output message or redirect to a thank you page, or something of the sort, but all I am seeing is a blank page, where there would have been the HTML form.
I have tried:
function doPost(e) {
//all logic
return ContentService.createTextOutput("Thank you");
}
And..
function doPost(e) {
//all logic
return ContentService.createTextOutput(JSON.stringify(e.parameter));
}
And..
function doPost(e) {
//all logic
var htmlBody = "<h1>Thank you.</h1>";
return HtmlService.createHtmlOutput(htmlBody);
}
And..
function doPost(e) {
//all logic
var template = HtmlService.createTemplateFromFile('Thanks');
return template.evaluate();
}
In all the listed cases the HTML form simply seems to disappear and I can only see a blank screen.
Any ideas?
In GAS, sending a POST request via web app is not as simple as it seems. Go ahead and try a little experiment: add the following JS code to the HTML page served by the doGet() function just before the closing <body> tag:
...
<script>
console.log(window.location);
</script>
</body>
When inspecting the output in the console, you'll likely get something like:
The issue is that the web app URL ending with '/exec' doesn't actually link to self. Ratner, the googleusercontent.com link is the URL you'll be redirected to when opening links and forms. However, in order to get the form submit to work, the POST request should be sent to the "published" URL of your web app (the one ending with '/exec').
You must therefore override the defaults by implementing your own routing. There are many ways to achieve this result - here's the easiest one:
<form method="post" action="<?!= ScriptApp.getService().getUrl() ?>">
<input type="submit" value="submit">
</form>
If the <?!= ?> notation looks unfamiliar to you, please check the section on scriptlets and HTML templates in GAS https://developers.google.com/apps-script/guides/html/templates
Basically, what happens is that the web app URL is force-printed to the template before raw HTML is sent to your browser for rendering. This makes sure you'll hit the correct URL when 'submit' event occurs.
My site fetches chart from spreadsheet but it is getting updated only when it is refreshed manually. Publishing on web is not working as expected. So Any method to refresh a site is much appreciated. Please do not include browser extensions or plugins or widgets, because of site audience.
After some hours struggling with this, i found a solution that worked for me.
Place this code in Templated HTML file. Then call function reloadSite() in Javascript to reload current site.
<script>
function reloadSite() {
window.top.location.href = '<?!= SitesApp.getActivePage().getUrl(); ?>';
}
</script>
Should be able to end the onSubmit() with the function that calls the Ui. You state it is doGet(), like this :
function onSubmit(e){
// Your code ...
doGet();
}