Anda dapat menggabungkan kode Apps Script dan HTML untuk menghasilkan halaman dinamis dengan sedikit upaya. Jika Anda telah menggunakan bahasa template yang mencampur kode dan HTML, seperti PHP, ASP, atau JSP, sintaksisnya akan terasa familier.
Skrip kecil
Template Apps Script dapat berisi tiga tag khusus, yang disebut skrip kecil. Di dalam skrip, Anda dapat menulis kode apa pun yang akan berfungsi dalam file Apps Script normal: skrip dapat memanggil fungsi yang ditentukan dalam file kode lain, mereferensikan variabel global, atau menggunakan salah satu Apps Script API. Anda bahkan dapat menentukan fungsi dan variabel dalam skrip kecil, dengan peringatan bahwa fungsi dan variabel tersebut tidak dapat dipanggil oleh fungsi yang ditetapkan dalam file kode atau template lainnya.
Jika Anda menempelkan contoh di bawah ke dalam editor skrip, isi tag
<?= ... ?>
(scriptlet pencetakan) akan muncul dalam
cetak miring. Kode yang dicetak miring tersebut berjalan di server sebelum halaman ditayangkan
kepada pengguna. Karena kode skrip skrip dieksekusi sebelum halaman ditayangkan, skrip tersebut hanya dapat berjalan sekali per halaman. Tidak seperti fungsi JavaScript sisi klien atau fungsi Apps Script yang Anda panggil melalui google.script.run
, skrip skrip tidak dapat dijalankan lagi setelah halaman dimuat.
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>
Perhatikan bahwa fungsi doGet()
untuk HTML template berbeda dengan contoh untuk membuat dan menayangkan HTML dasar. Fungsi yang ditampilkan di sini menghasilkan objek HtmlTemplate
dari file HTML, lalu memanggil metode evaluate()
untuk menjalankan skrip dan mengonversi template menjadi objek HtmlOutput
yang dapat ditayangkan oleh skrip kepada pengguna.
Skrip standar
Skrip kecil standar, yang menggunakan sintaksis <? ... ?>
, mengeksekusi kode tanpa
menghasilkan konten secara eksplisit ke halaman. Namun, seperti yang ditunjukkan contoh ini, hasil kode di dalam skrip masih dapat memengaruhi konten HTML di luar skrip:
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>
Mencetak skrip
Mencetak skrip kecil, yang menggunakan sintaksis <?= ... ?>
, menghasilkan hasil
kode ke dalam halaman menggunakan escape kontekstual.
escape kontekstual berarti Apps Script melacak konteks output
di halaman — di dalam atribut HTML, di dalam tag script
sisi klien, atau
di mana saja — dan otomatis menambahkan karakter escape
untuk melindungi dari serangan pembuatan skrip lintas situs (XSS).
Dalam contoh ini, skrip pertama yang mencetak output string secara langsung; diikuti dengan skrip standar yang menyiapkan array dan loop, diikuti dengan skrip pencetakan lain untuk menghasilkan isi array.
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>
Perlu diketahui bahwa skrip pencetakan hanya menghasilkan nilai dari pernyataan pertamanya;
pernyataan lainnya berperilaku seolah-olah dimuat dalam skrip
standar. Jadi, misalnya, skrip <?= 'Hello, world!'; 'abc' ?>
hanya
mencetak "Halo, dunia!"
Mencetak otomatis skrip kecil
Pencetakan paksa skrip, yang menggunakan sintaksis <?!= ... ?>
, seperti mencetak skrip
kecuali bahwa skrip tersebut menghindari escape kontekstual.
Pelarian kontekstual penting jika skrip Anda memungkinkan input pengguna yang tidak tepercaya. Sebaliknya, Anda harus mencetak paksa jika output skriplet Anda sengaja berisi HTML atau skrip yang ingin Anda sisipkan persis seperti yang ditentukan.
Sebagai aturan umum, gunakan mencetak skrip, bukan mencetak skrip secara paksa kecuali jika Anda tahu bahwa Anda perlu mencetak HTML atau JavaScript tanpa perubahan.
Kode Apps Script di skrip
Scriptlet tidak dibatasi untuk menjalankan JavaScript normal; Anda juga dapat menggunakan salah satu dari tiga teknik berikut untuk memberi template Anda akses ke data Apps Script.
Namun, ingat bahwa karena kode template dieksekusi sebelum halaman ditayangkan kepada pengguna, teknik ini hanya dapat memberikan feed konten awal ke halaman. Untuk mengakses
data Apps Script dari halaman secara interaktif, gunakan
google.script.run
API.
Memanggil fungsi Apps Script dari template
Scriptlet dapat memanggil fungsi apa pun yang ditentukan dalam library atau file kode Apps Script. Contoh ini menunjukkan satu cara untuk menarik data dari spreadsheet ke dalam template, lalu membuat tabel HTML dari data tersebut.
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>
Memanggil Apps Script API secara langsung
Anda juga dapat menggunakan kode Apps Script langsung di skrip. Contoh ini memberikan hasil yang sama seperti contoh sebelumnya dengan memuat data dalam template itu sendiri, bukan melalui fungsi terpisah.
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>
Mengirim variabel ke template
Terakhir, Anda dapat mengirim variabel ke dalam template dengan menetapkannya sebagai properti
objek HtmlTemplate
. Sekali lagi, contoh ini memberikan hasil yang sama seperti contoh sebelumnya.
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>
Template proses debug
Template dapat menjadi tantangan untuk di-debug karena kode yang Anda tulis tidak dijalankan secara langsung. Sebagai gantinya, server mengubah template Anda menjadi kode, lalu mengeksekusi kode yang dihasilkan tersebut.
Jika cara template dalam menginterpretasikan skrip Anda tidak jelas, dua
metode proses debug di
class HtmlTemplate
dapat membantu Anda
lebih memahami apa yang terjadi.
getCode()
getCode()
menampilkan
string yang berisi kode yang dibuat server dari template. Jika mencatat kode ke dalam log, lalu menempelkannya ke editor skrip, Anda dapat menjalankannya dan men-debug kode seperti kode Apps Script normal.
Berikut adalah template sederhana yang menampilkan lagi daftar produk Google,
diikuti dengan hasil getCode()
:
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>
CATAT (DIEVALUASI)
(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()
mirip dengan getCode()
, tetapi menampilkan kode yang dievaluasi sebagai komentar yang
muncul berdampingan dengan template asli.
Panduan kode yang dievaluasi
Hal pertama yang akan Anda lihat di kedua contoh kode yang dievaluasi adalah objek
output
implisit yang dibuat oleh metode HtmlService.initTemplate()
. Metode ini
tidak didokumentasikan karena hanya template itu sendiri yang perlu menggunakannya. output
adalah
objek HtmlOutput
khusus dengan dua
properti yang tidak diberi nama, _
dan _$
, yang merupakan singkatan untuk memanggil
append()
dan
appendUntrusted()
.
output
memiliki satu properti khusus lainnya, $out
, yang mengacu pada objek HtmlOutput
biasa yang tidak memiliki properti khusus ini. Template ini menampilkan objek normal tersebut di akhir kode.
Setelah Anda memahami sintaksis ini, kode selanjutnya seharusnya cukup mudah diikuti. Konten HTML di luar skrip kecil (seperti tag b
) ditambahkan
menggunakan output._ =
(tanpa escape kontekstual),
dan skrip ditambahkan sebagai JavaScript (dengan atau tanpa escape kontekstual,
bergantung pada jenis skrip).
Perhatikan bahwa kode yang dievaluasi mempertahankan nomor baris dari template. Jika Anda mendapatkan error saat menjalankan kode yang dievaluasi, baris akan sesuai dengan konten yang setara di dalam template.
Hierarki komentar
Karena kode yang dievaluasi mempertahankan nomor baris, komentar di dalam skrip dapat memberi komentar pada skrip kecil lain dan bahkan kode HTML. Contoh ini menunjukkan beberapa efek mengejutkan dari komentar:
<? 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. */ ?>