Sie können Apps Script-Code und HTML kombinieren, um dynamische Seiten mit minimalem Aufwand zu erstellen. Wenn Sie eine Vorlagensprache verwendet haben, in der Code und HTML gemischt werden, z. B. PHP, ASP oder JSP, sollte Ihnen die Syntax vertraut sein.
Scriptlets
Apps Script-Vorlagen können drei spezielle Tags enthalten, die als Scriptlets bezeichnet werden. In einem Scriptlet können Sie beliebigen Code schreiben, der in einer normalen Apps Script-Datei funktionieren würde: Scriptlets können Funktionen aufrufen, die in anderen Codedateien definiert sind, auf globale Variablen verweisen oder eine der Apps Script-APIs verwenden. Sie können sogar Funktionen und Variablen in Scriptlets definieren. Diese können jedoch nicht von Funktionen aufgerufen werden, die in Code-Dateien oder anderen Vorlagen definiert sind.
Wenn Sie das folgende Beispiel in den Skripteditor einfügen, wird der Inhalt des <?= ... ?>
-Tags (ein Druck-Scriptlet) kursiv dargestellt. Dieser kursiv formatierte Code wird auf dem Server ausgeführt, bevor die Seite an den Nutzer gesendet wird. Da Scriptlet-Code vor der Bereitstellung der Seite ausgeführt wird, kann er nur einmal pro Seite ausgeführt werden. Im Gegensatz zu clientseitigem JavaScript oder Apps Script-Funktionen, die Sie über google.script.run
aufrufen, können Scriptlets nach dem Laden der Seite nicht noch einmal ausgeführt werden.
Code.gs
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Hello, World! The time is <?= new Date() ?>.
</body>
</html>
Die doGet()
-Funktion für HTML-Vorlagen unterscheidet sich von den Beispielen für das Erstellen und Bereitstellen von einfachem HTML. Die hier gezeigte Funktion generiert ein HtmlTemplate
-Objekt aus der HTML-Datei und ruft dann die Methode evaluate()
auf, um die Scriptlets auszuführen und die Vorlage in ein HtmlOutput
-Objekt zu konvertieren, das vom Script an den Nutzer gesendet werden kann.
Standard-Scriptlets
Standard-Scriptlets, die die Syntax <? ... ?>
verwenden, führen Code aus, ohne explizit Inhalte auf der Seite auszugeben. Wie dieses Beispiel zeigt, kann das Ergebnis des Codes in einem Scriptlet jedoch weiterhin den HTML-Inhalt außerhalb des Scriptlets beeinflussen:
Code.gs
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<? if (true) { ?>
<p>This will always be served!</p>
<? } else { ?>
<p>This will never be served.</p>
<? } ?>
</body>
</html>
Scriptlets drucken
Mit Druck-Scriptlets, die die Syntax <?= ... ?>
verwenden, werden die Ergebnisse des zugehörigen Codes mithilfe von kontextbezogenem Escaping auf der Seite ausgegeben.
Beim kontextbezogenen Escaping wird der Ausgabekontext auf der Seite (in einem HTML-Attribut, in einem clientseitigen script
-Tag oder an einer anderen Stelle) von Apps Script verfolgt und es werden automatisch Escapezeichen hinzugefügt, um vor Cross-Site-Scripting-Angriffen (XSS) zu schützen.
In diesem Beispiel gibt das erste Druck-Scriptlet einen String direkt aus. Es folgt ein Standard-Scriptlet, das ein Array und eine Schleife einrichtet, gefolgt von einem weiteren Druck-Scriptlet, das den Inhalt des Arrays ausgibt.
Code.gs
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<?= 'My favorite Google products:' ?>
<? var data = ['Gmail', 'Docs', 'Android'];
for (var i = 0; i < data.length; i++) { ?>
<b><?= data[i] ?></b>
<? } ?>
</body>
</html>
Ein Druck-Scriptlet gibt nur den Wert der ersten Anweisung aus. Alle verbleibenden Anweisungen verhalten sich so, als wären sie in einem Standard-Scriptlet enthalten. Das Scriptlet <?= 'Hello, world!'; 'abc' ?>
gibt also nur „Hello, world!“ aus.
Scriptlets erzwingen
Scriptlets für den erzwungenen Druck, die die Syntax <?!= ... ?>
verwenden, ähneln Scriptlets für den Druck, vermeiden jedoch das kontextbezogene Escaping.
Kontextbezogenes Escaping ist wichtig, wenn Ihr Skript nicht vertrauenswürdige Nutzereingaben zulässt. Im Gegensatz dazu müssen Sie das Erzwingen des Drucks verwenden, wenn die Ausgabe Ihres Scriptlets absichtlich HTML oder Skripts enthält, die Sie genau wie angegeben einfügen möchten.
Verwenden Sie in der Regel Druck-Scriptlets anstelle von Force-Print-Scriptlets, es sei denn, Sie wissen, dass Sie HTML oder JavaScript unverändert drucken müssen.
Apps Script-Code in Scriptlets
Scriptlets sind nicht auf die Ausführung von normalem JavaScript beschränkt. Sie können auch eine der folgenden drei Techniken verwenden, um Ihren Vorlagen Zugriff auf Apps Script-Daten zu gewähren.
Da Vorlagencode jedoch ausgeführt wird, bevor die Seite dem Nutzer präsentiert wird, können mit diesen Methoden nur erste Inhalte auf einer Seite bereitgestellt werden. Wenn Sie interaktiv von einer Seite aus auf Apps Script-Daten zugreifen möchten, verwenden Sie stattdessen die google.script.run
API.
Apps Script-Funktionen über eine Vorlage aufrufen
In Scriptlets kann jede Funktion aufgerufen werden, die in einer Apps Script-Codedatei oder -Bibliothek definiert ist. In diesem Beispiel wird gezeigt, wie Sie Daten aus einer Tabelle in eine Vorlage einfügen und dann eine HTML-Tabelle aus den Daten erstellen.
Code.gs
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
function getData() {
return SpreadsheetApp
.openById('1234567890abcdefghijklmnopqrstuvwxyz')
.getActiveSheet()
.getDataRange()
.getValues();
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<? var data = getData(); ?>
<table>
<? for (var i = 0; i < data.length; i++) { ?>
<tr>
<? for (var j = 0; j < data[i].length; j++) { ?>
<td><?= data[i][j] ?></td>
<? } ?>
</tr>
<? } ?>
</table>
</body>
</html>
Apps Script-APIs direkt aufrufen
Sie können Apps Script-Code auch direkt in Scriptlets verwenden. In diesem Beispiel wird dasselbe Ergebnis wie im vorherigen Beispiel erzielt, indem die Daten in die Vorlage selbst geladen werden und nicht über eine separate Funktion.
Code.gs
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<? var data = SpreadsheetApp
.openById('1234567890abcdefghijklmnopqrstuvwxyz')
.getActiveSheet()
.getDataRange()
.getValues(); ?>
<table>
<? for (var i = 0; i < data.length; i++) { ?>
<tr>
<? for (var j = 0; j < data[i].length; j++) { ?>
<td><?= data[i][j] ?></td>
<? } ?>
</tr>
<? } ?>
</table>
</body>
</html>
Variablen in Vorlagen einfügen
Schließlich können Sie Variablen in eine Vorlage einfügen, indem Sie sie als Attribute des Objekts HtmlTemplate
zuweisen. Auch in diesem Beispiel wird dasselbe Ergebnis wie in den vorherigen Beispielen erzielt.
Code.gs
function doGet() {
var t = HtmlService.createTemplateFromFile('Index');
t.data = SpreadsheetApp
.openById('1234567890abcdefghijklmnopqrstuvwxyz')
.getActiveSheet()
.getDataRange()
.getValues();
return t.evaluate();
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<table>
<? for (var i = 0; i < data.length; i++) { ?>
<tr>
<? for (var j = 0; j < data[i].length; j++) { ?>
<td><?= data[i][j] ?></td>
<? } ?>
</tr>
<? } ?>
</table>
</body>
</html>
Fehlerbehebung bei Vorlagen
Das Debuggen von Vorlagen kann schwierig sein, da der von Ihnen geschriebene Code nicht direkt ausgeführt wird. Stattdessen wandelt der Server Ihre Vorlage in Code um und führt diesen resultierenden Code dann aus.
Wenn nicht klar ist, wie die Vorlage Ihre Scriptlets interpretiert, können Sie zwei Debugging-Methoden in der Klasse HtmlTemplate
verwenden, um besser zu verstehen, was passiert.
getCode()
getCode()
gibt einen String mit dem Code zurück, den der Server aus der Vorlage erstellt. Wenn Sie den Code protokollieren und dann in den Skripteditor einfügen, können Sie ihn wie normalen Apps Script-Code ausführen und debuggen.
Hier ist die einfache Vorlage, in der noch einmal eine Liste der Google-Produkte und dann das Ergebnis von getCode()
angezeigt wird:
Code.gs
function myFunction() {
Logger.log(HtmlService
.createTemplateFromFile('Index')
.getCode());
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<?= 'My favorite Google products:' ?>
<? var data = ['Gmail', 'Docs', 'Android'];
for (var i = 0; i < data.length; i++) { ?>
<b><?= data[i] ?></b>
<? } ?>
</body>
</html>
LOG (EVALUATED)
(function() { var output = HtmlService.initTemplate(); output._ = '<!DOCTYPE html>\n';
output._ = '<html>\n' +
' <head>\n' +
' <base target=\"_top\">\n' +
' </head>\n' +
' <body>\n' +
' '; output._$ = 'My favorite Google products:' ;
output._ = ' '; var data = ['Gmail', 'Docs', 'Android'];
for (var i = 0; i < data.length; i++) { ;
output._ = ' <b>'; output._$ = data[i] ; output._ = '</b>\n';
output._ = ' '; } ;
output._ = ' </body>\n';
output._ = '</html>';
/* End of user code */
return output.$out.append('');
})();
getCodeWithComments()
getCodeWithComments()
ist ähnlich wie getCode()
, gibt aber den ausgewerteten Code als Kommentare zurück, die nebeneinander mit der ursprünglichen Vorlage angezeigt werden.
Ausgewerteten Code durchgehen
Das Erste, was Sie in beiden Beispielen für ausgewerteten Code bemerken werden, ist das implizite output
-Objekt, das von der Methode HtmlService.initTemplate()
erstellt wird. Diese Methode ist nicht dokumentiert, da sie nur von Vorlagen selbst verwendet werden muss. output
ist ein spezielles HtmlOutput
-Objekt mit zwei ungewöhnlich benannten Properties, _
und _$
, die eine Kurzform für den Aufruf von append()
und appendUntrusted()
sind.
output
hat eine weitere spezielle Eigenschaft, $out
, die sich auf ein reguläres HtmlOutput
-Objekt bezieht, das diese speziellen Eigenschaften nicht besitzt. Die Vorlage gibt dieses normale Objekt am Ende des Codes zurück.
Nachdem Sie diese Syntax verstanden haben, sollte der Rest des Codes relativ einfach nachzuvollziehen sein. HTML-Inhalte außerhalb von Scriptlets (z. B. das b
-Tag) werden mit output._ =
angehängt (ohne kontextbezogene Escapesequenzen). Scriptlets werden als JavaScript angehängt (mit oder ohne kontextbezogene Escapesequenzen, je nach Art des Scriptlets).
Beachten Sie, dass im ausgewerteten Code die Zeilennummern aus der Vorlage beibehalten werden. Wenn beim Ausführen des ausgewerteten Codes ein Fehler auftritt, entspricht die Zeile dem entsprechenden Inhalt in der Vorlage.
Hierarchie der Kommentare
Da bei ausgewertetem Code Zeilennummern beibehalten werden, können mit Kommentaren in Scriptlets andere Scriptlets und sogar HTML-Code auskommentiert werden. Diese Beispiele zeigen einige überraschende Auswirkungen von Kommentaren:
<? var x; // a comment ?> This sentence won't print because a comment begins inside a scriptlet on the same line. <? var y; // ?> <?= "This sentence won't print because a comment begins inside a scriptlet on the same line."; output.append("This sentence will print because it's on the next line, even though it's in the same scriptlet.”) ?> <? doSomething(); /* ?> This entire block is commented out, even if you add a */ in the HTML or in a <script> */ </script> tag, <? until you end the comment inside a scriptlet. */ ?>