Google Apps Script Templated HTML - google-apps-script

Has "Google Apps Script templates" been deprecated. When the showSidebar code is run below it displays the following in the sidebar:
Hello, World! The time is .
==========================
File: code.gs
function showSidebar() {
var ui = HtmlService.createHtmlOutputFromFile('index')
.setTitle('test');
SpreadsheetApp.getUi().showSidebar(ui);
}
======================
File: index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Hello, World! The time is <?= new Date() ?>.
</body>
</html>
Here is the link to google documentation on apps script templates
https://developers.google.com/apps-script/guides/html/templates

No, templates have not been Deprecated.
Rather than use createHtmlOutputFromFile(), you must use createHtmlTemplateFromFile(), then evaluate the template with evaluate() to generate your HtmlOutput.
This process is shown in at the top of the documentation you linked.

Related

How do I pass a variable from GAS to HTML and back?

I am using GAS to create a web app. I have a doGet that generates the HTML page for the web app and a button on the web app that triggers a script. When I create the HTML page, there is a variable that I need to send to the web app that is then sent back to the script. That variable isn't used in the HTML page other than just transferring it.
Here is a minimal example of what I want to do:
My doGet() creates the HTML and passes the variable foo to the page
function doGet(e) {
var htmlOutput = HtmlService.createTemplateFromFile("page");
var foo = "12345";
htmlOutput.foo = foo;
return htmlOutput.evaluate().setTitle('Sample');
}
The HTML page has a button that, when clicked, should pass the variable foo back to GAS to run the function checkOut
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<button id="btn" onclick="doStuff()">Click Here</button>
<script>
function doStuff(){
google.script.run.checkOut(foo);
}
</script>
</body>
</html>
In this example, checkOut just displays foo
function checkOut(foo){
Logger.log(foo);
}
I don't want foo displayed anywhere on the HTML page, but what should I add in order to get it sent back to GAS?
TIA
I believe your goal is as follows.
You want to use a value of foo in the function of checkOut at Google Apps Script side.
From That variable isn't used in the HTML page other than just transferring it. and I don't want foo displayed anywhere on the HTML page, you want to achieve this without including the value of foo in the HTML data.
In this case, how about the following modification?
Modified script 1:
In this modification, the value of foo is used with the scriptlets. This has already been mentioned in the comment.
In this method, the value of foo is shown in the HTML data like google.script.run.checkOut("12345"). I'm worried that this might not your expected situation from I don't want foo displayed anywhere on the HTML page. How about this?
Google Apps Script side:
function doGet(e) {
var htmlOutput = HtmlService.createTemplateFromFile("page");
var foo = "12345";
htmlOutput.foo = foo;
return htmlOutput.evaluate().setTitle('Sample');
}
function checkOut(foo){
Logger.log(foo);
}
HTML & Javascript side:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<button id="btn" onclick="doStuff()">Click Here</button>
<script>
function doStuff(){
google.script.run.checkOut("<?!= foo ?>");
}
</script>
</body>
</html>
Modified script 2:
In this modification, the value of foo is used as the background side (Google Apps Script side).
In this method, the value of foo is not shown in the HTML data.
Google Apps Script side:
function doGet(e) {
var foo = "12345";
PropertiesService.getScriptProperties().setProperty("sampleKey", foo);
var htmlOutput = HtmlService.createHtmlOutputFromFile("page");
return htmlOutput.setTitle('Sample');
}
function checkOut(){
var foo = PropertiesService.getScriptProperties().getProperty("sampleKey");
Logger.log(foo);
}
HTML & Javascript side:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<button id="btn" onclick="doStuff()">Click Here</button>
<script>
function doStuff(){
google.script.run.checkOut();
}
</script>
</body>
</html>
References:
HTML Service: Templated HTML
Properties Service
SUGGESTION
As what the TheWizEd has commented, you can also achieve your goal using the withSuccessHandler(). You may check this tweaked script below using a different implementation:
Code.gs
function doGet(e) {
var htmlOutput = HtmlService.createTemplateFromFile("page");
return htmlOutput.evaluate().setTitle('Sample');
}
function setupFoo(){ //Define a value for the "foo"
return "12345";
}
function checkOut(foo){
Logger.log(foo);
}
page.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<button id="btn" onclick="doStuff()">Click Here</button>
<script>
function onSuccess(foo) {
google.script.run.checkOut(foo); //on Success will pass back the foo value to GAS function "checkOut"
}
function doStuff(){
google.script.run.withSuccessHandler(onSuccess).setupFoo(); //Run "setupFoo" function & pass its returned value to the "withSuccessHandler" function named "onSuccess"
}
</script>
</body>
</html>
Demonstration
After clicking the Click Here button on the web app, checkOut will log the foo value:

Download a created Google Doc from a deployed web app

I've created a script that, when deployed as a web app, asks the user for some input, and creates and writes to a Google document.
Apparently, downloading the Google document from the script is not possible, and the next best thing seems to convert the doc and save it in My Drive.
I have tried this very simple approach, inspired by Convert Google Doc to PDF using Google Script Editior
Project is deployed as a web app
Code.gs:
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function editDoc(data) {
let doc = DocumentApp.create("Title");
let body = doc.getBody();
body.setText(data);
docblob = doc.getAs('application/pdf');
docblob.setName(doc.getName() + ".pdf");
let file = DriveApp.createFile(docblob);
}
Index.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form onsubmit="edit()">
<input type="text" id="input">
<input type="submit" id="sub" value="Submit">
</form>
<script>
function edit() {
google.script.run.editDoc(document.getElementById("input").value);
}
</script>
</body>
</html>
As a result, this adds a pdf to my google drive, which should be the pdf form of the created google doc, however it is blank.
I believe your goal as follows.
You want to create new Google Document including the value from the input tag.
And, you want to export the Google Document as a PDF file.
You want to achieve this using Google Apps Script.
Modification points:
I think that the reason of however it is blank is that the Document is not saved.
In order to download the PDF file, I would like to propose to convert the PDF data to the base64 data and set it as the data URL, and then, download it.
When above points are reflected to your script, it becomes as follows.
Modified script:
Google Apps Script side: Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function editDoc(data) {
let doc = DocumentApp.create("Title");
let body = doc.getBody();
body.setText(data);
doc.saveAndClose();
return {
data: "data:application/pdf;base64," + Utilities.base64Encode(doc.getBlob().getBytes()),
filename: doc.getName() + ".pdf"
};
}
HTML & Javascript side: Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form onsubmit="event.preventDefault(); edit();">
<input type="text" id="input">
<input type="submit" id="sub" value="Submit">
</form>
<script>
function edit() {
google.script.run.withSuccessHandler(({data, filename}) => {
const a = document.createElement("a");
document.body.appendChild(a);
a.download = filename;
a.href = data;
a.click();
}).editDoc(document.getElementById("input").value);
}
</script>
</body>
</html>
I thought that in this case, a simple button can be also used instead of the submit button.
In the case of Google Docs, when a blog is retrieved, in the current stage, the blob is the PDF format.
In this modified script, when a text is inputted and a button is clicked, a PDF file is downloaded to the local PC.
Note:
In your script, it seems that Web Apps is used. In this case, when the script of Web Apps is modified, please redeploy the Web Apps as new version. By this, the latest script is reflected to the Web Apps. Please be careful this.
References:
Class google.script.run
saveAndClose()
base64Encode(data)

"No functions have been run in this editor session" - Issue with Google App Script [duplicate]

This question already has answers here:
How can I test a trigger function in GAS?
(4 answers)
How to view the logging of Google Web App when other users are executing it?
(2 answers)
Closed 1 year ago.
I am trying to create a webapp using Google Apps Script.
However, when I deploy my project(in a new version) as webapp and then view Log, it shows "No functions have been run in this editor session" message.
The HTML Code is saved as "page.html" (as expected by the function). Please help me
function doGet(e)
{
return HtmlService.createHtmlOutputFromFile("page");
Logger.log(e);
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h1> Hello 3 </h1>
</body>
</html>
You have 2 small issues,
1.- Your doGet(e) is executing the return statement before you actually log the e event. and so Logger.log(e); is not executed.
2.- The Apps script Logger class only works in the apps script session. (You would have to execute the function from within the editor to see this log). Also keep in mind that doGet(e) when run from within the editor will have a null e, but when making a GET request to your deployed webapp it will not be null.
Solution:
function doGet(e){
// Log the event in StackDriver
console.log(e);
return HtmlService.createHtmlOutputFromFile("page");
}
Here's a quick dialog:
GS:
function showDialog() {
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutputFromFile("page"), 'test');
}
function sayHowdy() {
return "Howdy";
}
HTML:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h1> Hello 3 </h1>
<input id="msg" type="text" readonly />
<input type="button" value="Say Hello" onClick="sayHello()" />
<script>
function sayHello() {
google.script.run
.withSuccessHandler(function(msg){
document.getElementById('msg').value=msg;
})
.sayHowdy()
}
</script>
</body>
</html>

How to connect css to html in Google Apps Scripts

I'm trying to make my first Google App. I have my HTML doc which has the include statement as outlined on HTML Service: Best Practices.
<html>
<head>
<base target="_top">
<?!= include('stylesheet') ?>
</head>
<body>
...
</body>
My code.gs file is as follows:
function doGet() {
return HtmlService.createTemplateFromFile('BooksTS2.html')
.evaluate();
}
My style sheet is named stylesheet.html, and for testing purposes is really simple:
<style>
p {color: green;}
</style>
But when I run it I get this error message: ReferenceError: "include" is not defined.
In the example they created the reusable function include(), you need to add it in your code.gs file:
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
You can always use the printing scriptlet directly in your html file like this:
<html>
<head>
<base target="_top">
<?!= HtmlService.createHtmlOutputFromFile('stylesheet').getContent(); ?>
</head>
<body>
...
</body>
</html>

How to call google script function from a HTML file?

I have created a web page through the Html Services api in google apps script. In the script, I have one google script(.gs) file and two html files(.html). This script is published on web. To display html file on web I used following function in .gs file:
function doGet() { //Published on web
return HtmlService.createTemplateFromFile('<htmlFile_1>').evaluate();
}
function doProcess() {
return HtmlService.createTemplateFromFile('<htmlFile_2>').evaluate();
}
doGet() is returning this Html file on the web. Now I want to display another Html File by replacing this file. So, I used following in htmlFile_1:
//htmlFile_1.html
<html>
<head>
<script>
function loadMainHtmlPage(){
google.script.run.doProcess(); //calling another function in .gs file
setTimeout(function(){hello()},4000);
}
function hello(){
alert("hiii");
document.getElementById("loading").style.display="none";}
</script>
</head>
<body onload="loadMainHtmlPage();">
<div id="loading" style="display:block;">
<img src="http://commondatastorage.googleapis.com/kickoff/loading.gif"/>
</div>
</body>
</html>
This htmlFile_1 is not calling the doProcess(), that would return the htmlFile_2.'
Any suggestion to implement this?
You need to include an onSuccess (and optionally an onFailure) handler on this line of code
google.script.run.doProcess();
See below
Server code
function getSuperHero() {
return {name: "SuperGeek", catch_phrase: "Don't worry ma'am, I come from the Internet" };
}
Client code
<script>
function onSuccess(hero) {
alert (hero.catch_phrase);
}
google.script.run.withSuccessHandler(onSuccess).getSuperHero();
</script>