Layanan HTML: HTML template

Anda dapat menggabungkan kode Apps Script dan HTML untuk menghasilkan halaman dinamis dengan usaha. Jika Anda telah menggunakan bahasa template yang mencampur kode dan HTML, seperti PHP, ASP, atau JSP, sintaksisnya harus terasa familier.

Skriplet

Template Apps Script dapat berisi tiga tag khusus, yang disebut skriplet. Di dalam sebuah skrip, Anda dapat menulis kode apa pun yang akan berfungsi di Apps Script normal file: scriptlet dapat memanggil fungsi yang ditentukan dalam file kode lainnya, variabel global, atau menggunakan Apps Script API. Anda bahkan dapat menentukan fungsi dan variabel dalam scriptlet, dengan peringatan bahwa mereka tidak dipanggil oleh fungsi yang ditentukan dalam file kode atau {i>template<i} lainnya.

Jika Anda menempelkan contoh di bawah ini ke dalam editor skrip, konten dari Tag <?= ... ?> (scriptlet pencetakan) akan muncul di miring. Kode yang dicetak miring tersebut berjalan di server sebelum halaman ditayangkan kepada pengguna. Karena kode {i>scriptlet<i} dieksekusi sebelum laman ditayangkan, itu hanya dapat berjalan sekali per halaman; tidak seperti JavaScript sisi klien atau Apps Script fungsi yang Anda panggil google.script.run, skriplet tidak dapat dieksekusi 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 dengan template berbeda dengan contoh untuk membuat dan menampilkan HTML dasar. {i>Function<i} yang ditampilkan di sini akan membuat Objek HtmlTemplate dari HTML , lalu memanggilnya Metode evaluate() untuk mengeksekusi {i>scriptlet<i} dan mengonversi {i>template<i} menjadi HtmlOutput yang oleh skrip dapat ditayangkan kepada pengguna.

Scriptlet standar

Scriptlet standar, yang menggunakan sintaksis <? ... ?>, mengeksekusi kode tanpa secara eksplisit menampilkan konten pada halaman. Namun, seperti yang ditunjukkan contoh ini, hasil kode di dalam skriplet masih dapat memengaruhi konten HTML di luar {i>scriptlet<i}:

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 skriplet

Scriptlet pencetakan, yang menggunakan sintaksis <?= ... ?>, menampilkan hasil kode mereka ke dalam laman menggunakan escaping kontekstual.

Escape kontekstual berarti Apps Script melacak konteks output di halaman — di dalam atribut HTML, di dalam tag script sisi klien, atau di tempat lain — dan otomatis menambahkan karakter escape untuk melindungi dari serangan pembuatan skrip lintas situs (XSS).

Dalam contoh ini, skriplet pencetakan pertama menghasilkan string secara langsung; ini diikuti oleh skriplet standar yang mengatur sebuah {i>array<i} dan sebuah loop, diikuti oleh skriplet cetak yang lain untuk menghasilkan isi dari {i>array<i}.

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>

Perhatikan bahwa skriplet pencetakan hanya menghasilkan nilai pernyataan pertamanya; setiap pernyataan yang tersisa berperilaku seolah-olah berada dalam {i>scriptlet<i}. Jadi, misalnya, skriplet <?= 'Hello, world!'; 'abc' ?> saja mencetak "Hello, world!" (Halo dunia)

Mencetak otomatis skriplet

Mencetak otomatis skriplet, yang menggunakan sintaksis <?!= ... ?>, mirip seperti mencetak {i>scriptlet<i} kecuali bahwa mereka menghindari pelarian kontekstual.

Escape kontekstual penting jika skrip Anda mengizinkan input pengguna yang tidak tepercaya. Menurut kontras, Anda harus mencetak paksa jika output scriptlet Anda sengaja berisi HTML atau skrip yang ingin Anda sisipkan persis seperti yang ditentukan.

Sebagai aturan umum, gunakan skriplet pencetakan, bukan skriplet mencetak paksa kecuali Anda tahu bahwa Anda harus mencetak HTML atau JavaScript tanpa perubahan.

Kode Apps Script di skriplet

Skrip tidak dibatasi untuk menjalankan JavaScript normal; Anda juga dapat menggunakan dari tiga teknik berikut untuk memberi template Anda akses ke Apps Script layanan otomatis dan data skalabel.

Namun, harap diingat bahwa karena kode template dieksekusi sebelum halaman ditayangkan kepada pengguna, teknik ini hanya dapat memasukkan konten awal ke sebuah 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 salah satu cara untuk menarik data dari {i>spreadsheet<i} ke dalam {i>template<i}, kemudian membuat sebuah tabel HTML dari data itu.

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 API Apps Script secara langsung

Anda juga dapat menggunakan kode Apps Script langsung di skriplet. Contoh ini memberikan hasil yang sama seperti contoh sebelumnya dengan memuat data di {i>template<i} itu sendiri daripada melalui fungsi yang 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 memasukkan variabel ke dalam template dengan menetapkannya sebagai properti objek HtmlTemplate. Satu kali sekali lagi, contoh ini memberikan hasil yang sama dengan 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 sulit untuk di-debug karena kode yang Anda tulis tidak dieksekusi secara langsung; sebagai gantinya, server akan mengubah {i> template<i} Anda menjadi kode, lalu mengeksekusi pada kode yang dihasilkan.

Jika cara template menafsirkan {i>scriptlet<i} Anda tidak terlihat jelas, dua metode-metode {i>debugging <i}di Class HtmlTemplate dapat membantu Anda lebih memahami apa yang sedang terjadi.

getCode()

getCode() menampilkan yang berisi kode yang dibuat server dari template. Jika Anda mencatat kode, lalu menempelkannya ke editor skrip, Anda dapat menjalankannya dan men-debug seperti biasa kode Apps Script.

Berikut adalah {i>template<i} 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 (EVALUASI)

(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 akan muncul berdampingan dengan template aslinya.

Panduan kode yang dievaluasi

Hal pertama yang akan Anda perhatikan di kedua contoh kode yang dievaluasi adalah Objek output dibuat dengan metode HtmlService.initTemplate(). Metode ini tidak terdokumentasi karena hanya template yang diperlukan untuk menggunakannya. output adalah objek HtmlOutput khusus dengan dua properti bernama tidak biasa, _ dan _$, yang merupakan singkatan untuk memanggil append() dan appendUntrusted().

output memiliki satu properti khusus lainnya, $out, yang mengacu pada HtmlOutput yang tidak memiliki properti khusus ini. {i>Template<i} mengembalikan objek normal tersebut di akhir kode.

Sekarang setelah Anda memahami {i>syntax<i} ini, kode lainnya seharusnya cukup mudah untuk diikuti. Konten HTML di luar skriplet (seperti tag b) ditambahkan menggunakan output._ = (tanpa penggantian kontekstual), dan skriplet ditambahkan sebagai JavaScript (dengan atau tanpa escaping kontekstual, tergantung pada jenis {i>scriptlet<i}).

Perhatikan bahwa kode yang dievaluasi mempertahankan nomor baris dari template. Jika Anda mendapatkan {i>error<i} saat menjalankan kode yang dievaluasi, baris akan sesuai dengan konten yang setara dalam template.

Hierarki komentar

Karena kode yang dievaluasi mempertahankan jumlah baris, komentar dapat menjadi mungkin di dalam {i>scriptlet<i} untuk mengomentari {i>scriptlet<i} lain dan bahkan kode HTML. Ini contoh menunjukkan beberapa efek komentar yang mengejutkan:

<? 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. */ ?>