What is the difference between the Google App Script Scriptlets? [duplicate] - google-apps-script

Is the tag <?= ?> a specific syntax of Google scripts or it could work in a pure html/javascript page? Is there any description for it?
That is similar to <?=$a; ?> PHP tag but I doubted when I saw this: <? var foo = "test"; ?>.

Officially, these bits of code are referred to as 'scriptlets' in GAS documentation. They are Apps Script syntax for server-side HTML rendering.
Before HTML content is sent to your browser for client-side rendering all scripts between <? ?> and <?! ?> are executed and their output gets appended to the template.
It could also be just plain text between these tags instead of scripts.
Scriptlets get executed when you convert an HtmlTemplate to a HtmlOutput object in GAS:
//HtmlTemplate instance
var htmlTemplate = HtmlService.createTemplate("<a href='<?!= www.google.com ?>'>Google</a>");
//HtmlOutputInstance - calling evaluate() fires off the scriptlets and
//creates HTML output that is ready to be sent to the client.
var htmlOutput = htmlTemplate.evaluate();
//Logs <a href='www.google.com'> Google </a>
Logger.log(htmlOutput.getContent());
The short answer is no. You can't run scriptlets directly in your browser - they are executed on Google Servers. You are correct that there are many templating engines that serve the same function but are implemented differently.

Related

What is the purpose of HTML evaluation in Apps Script?

I am currently learning Apps Script fundamentals. I've encounter a method:
evaluate()
e.g.
const htmlServ = HtmlService.createTemplateFromFile("main");
const html = htmlServ.evaluate(); //
Within the reference it says:
It evaluates template and returns an HtmlOutput object.
My question: Does evaluate() has anything to do with security internally in Apps Script? Any relationship with HTML entities and its escaping? I want to clear this out.
Thanks.
evaluate() just injects data to your HTML templates. AFAIK it has nothing to do with the security.
The most common use case of this mechanism is when you have (nicely styled :)) HTML template that you want to have dynamic data. For example you have daily report that you want to display on a HTML page or send by email that has HTML body. But each day your Daily Total Revenue is different. You would do something like this:
<!-- Inside index.html file -->
<html>
<div class=my-class">
<p>Daily Total Revenue is: <?= dailyTotalRevenueVar ?>.</p>
</div>
</html>
// Inside Code.gs file
const template = HtmlService.createTemplateFromFile("index");
template.dailyTotalRevenueVar = 1000000; // Add a property to the template
const htmlOutput = template.evaluate(); // Replace var in HTML with actual value 1000000
Logger.log(htmlOutput.getContent()); // or return as a result in doGet()
You have many more options besides the simple value replacing, you can skip the entire HTML block if array has zero length, you can make a for loop to fill the select options...
Take a look at this page (toggle between .gs and .html view in code examples)
https://developers.google.com/apps-script/guides/html/templates
For more info about doGet and publishing GAS project as a web application visit this page:
https://developers.google.com/apps-script/guides/web

Redirecting from doPost() in Google Web App, HTML form with App script

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.

Google application script <?= var ?>

I am trying to print a variable from the .gs code within an HTML document using
<?= var ?>
I know I have done this before, but when I do it now, the entire tag is just rendered - so the page displays
<?= var ?>
rather than do anything with GAS.
Yea, that checks out. You CAN use the .createTemplateFromFile with viewport, and must use .createTemplateFromFile not .createTemplateFromFile with any scripting.
Simple enough, just don't use it often enough to keep it all straight.

Google Apps Script Web App: Can't separate out css and js code

I'm trying to separate my javascript and stylesheet from the main HTML file in my Google Apps Spreadsheet script that is published as a Web App. I have seen this answer to the problem, but I cannot get this approach to work for me.
When I have my stylesheet and javascript in the main HTML file, it works fine. When I try to separate them exactly as the answer recommends, the stylesheet and javascript code is not processed and instead the line that calls 'getContent()' is displayed in my browser. It looks like getContent() is not being executed at all.
I've tried moving my code away from the Spreadsheet to a Standalone Web App but still have the same problem. Any ideas why it's not working for me? Thank you!
A bit from my Code.gs:
function doGet() {
var output = HtmlService.createHtmlOutputFromFile('index');
output.setSandboxMode(HtmlService.SandboxMode.IFRAME);
output.setTitle('Dashboard Tool');
return output;
}
function getContent(filename) {
Logger.log('getContent()');
return HtmlService.createTemplateFromFile(filename).getRawContent();
}
index.html:
<?!= getContent("stylesheet") ?>
<div class='header'>Dashboard</div>
<div id=content>
Content Here
</div>
<?!= getContent("javascript") ?>
'stylesheet.html' code is surrounded by the style tag and 'javascript.html' code is surrounded by the script tag.
You forgot evaluate() in the createHtmlOutputFromFile(), also you should use the createTemplateFromFile, as such.
var output = HtmlService.createTemplateFromFile('index').evaluate();
As #brian-p pointed out, you need the 'Template' instead of 'Output', for the evaluate occur on the scriplets <?!= ?>.
In this line of code:
return HtmlService.createTemplateFromFile(filename).getRawContent();
createTemplateFromFile() is being used. That method is for creating the original template, but the getContent() function is not for that purpose. Use:
return HtmlService.createHtmlOutputFromFile(filename).getContent();

Retrieving HTML code used in google docs using google app scripts

Is it possible to use Google app scripts to get the html code in Google docs i.e if text in the document was say bold,i could get the html code for that.
What i have so far :
function getHtml(id) {
var doc1=DocsListExtended.getFileById("1ta7zJ6SDFgzgp-UprjehxR8Tx3-4-wtJwTYqWbol1SU").getAsHTML();
var body=HtmlService.createHtmlOutput(doc1);
var cont=body.getContent();
return cont;
Logger.log(cont);
}
I don't know a simple way for that. You can navigate the elements of the document using DocumentApp API, and converting it block by block to HTML.
I already tried
DocumentApp.getActiveDocument().getAs(MimeType.HTML).getDataAsString()
but the error says doc can't be converted to html mimetype.