Mulai menggunakan visualisasi kustom di Looker

Looker Visualization API adalah JavaScript API yang berjalan di iframe dengan sandbox dan dihosting dalam aplikasi Looker.

Anda dapat menggunakan kode visualisasi yang sama untuk memberikan visualisasi di mana saja di Looker: Explore, Look, dasbor, sematan, atau PDF atau gambar yang dirender.

Setiap visualisasi menampilkan tampilan satu kueri Looker. Looker menjalankan kueri dan meneruskan hasilnya ke kode visualisasi Anda. Looker juga meneruskan elemen DOM yang dapat digambar oleh kode visualisasi Anda.

Persyaratan

Sebelum memulai, pastikan Anda memenuhi persyaratan berikut:

  • Anda perlu memiliki sedikit pengetahuan tentang JavaScript dan pengembangan web.
  • Akses Admin Looker diperlukan untuk membuat dan memperbarui file manifes project LookML.

Membuat visualisasi Halo Dunia

Bagian ini menjelaskan cara membuat skrip visualisasi kustom yang menampilkan dimensi pertama dari kueri tertentu.

Hasil akhirnya akan terlihat seperti gambar berikut:

Penyiapan

Untuk mengembangkan dan menguji visualisasi di Looker, Anda memiliki dua opsi:

Setelah mengonfigurasi salah satu opsi ini, Anda dapat mengikuti contoh di bagian ini untuk membuat hello_world.js.

Struktur kode penting

Untuk melihat kode sumber akhir contoh ini, lihat repositori GitHub.

Di folder tempat Anda menghosting, buat file JavaScript kosong baru dan beri nama hello_world.js.

Untuk mendaftarkan visualisasi kustom baru ke Looker, panggil fungsi looker.plugins.visualizations.add dan teruskan objek visualisasi ke fungsi tersebut. Objek ini berisi definisi visualisasi dan UI konfigurasinya.

Contoh berikut menunjukkan kerangka visualisasi dengan semua properti yang diperlukan terisi. File ini berisi fungsi create dan fungsi updateAsync tempat Anda dapat menulis kode visualisasi:

looker.plugins.visualizations.add({
  create: function(element, config) {

  },
  updateAsync: function(data, element, config, queryResponse, details, done) {

  }
})

Kode ini adalah visualisasi Looker yang valid, tetapi belum terlihat dan muncul sebagai kotak kosong.

Persiapan awal

Pertimbangkan fungsi create, yang memiliki dua argumen: element dan config.

Looker menyediakan element, yaitu elemen DOM yang mengharuskan Anda menempatkan visualisasi ke dalamnya. Looker membuat elemen ini dan menyesuaikan ukurannya; Anda harus menempatkan konten di dalamnya.

Fungsi create memberikan peluang untuk melakukan penyiapan awal elemen Anda. Untuk contoh ini, Anda ingin membuat diagram yang menyerupai struktur HTML berikut:

<style>
  /* custom styles for your chart */
</style>
<div class="hello-world-vis">
  <div>Data Goes Here</div>
</div>

Dengan menggunakan JavaScript, Anda dapat menyisipkan elemen ke dalam elemen DOM agar sesuai dengan struktur ini.

Contoh berikut menunjukkan fungsi ini dengan menambahkan detail lainnya:

create: function(element, config) {

  // Insert a <style> tag with some styles to use later.
  var css = element.innerHTML = `
    <style>
      .hello-world-vis {
        /* Vertical centering */
        height: 100%;
        display: flex;
        flex-direction: column;
        justify-content: center;
        text-align: center;
      }
    </style>
  `;

  // Create a container element to center the text.
  var container = element.appendChild(document.createElement("div"));
  container.className = "hello-world-vis";

  // Create an element to contain the text.
  this._textElement = container.appendChild(document.createElement("div"));

},

Kode ini menambahkan CSS, membuat penampung hello-world-vis, dan menambahkan div di dalamnya.

Kode ini juga menetapkan this._textElement ke penampung yang ingin Anda render. Hal ini memudahkan Anda sehingga tidak perlu mencarinya lagi nanti saat diagram mulai dirender.

Fungsi create adalah tempat yang tepat untuk melakukan tugas penyiapan yang hanya perlu dilakukan sekali.

Rendering

Bagian ini menjelaskan cara memperluas metode updateAsync untuk memvisualisasikan data. Metode ini dipanggil setiap kali diagram harus memvisualisasikan perubahan atau saat peristiwa lain terjadi yang mungkin memengaruhi cara diagram dirender (misalnya, diagram diubah ukurannya atau opsi konfigurasi berubah).

Untuk contoh ini, Anda hanya perlu menemukan dimensi pertama di sel pertama. Anda dapat melakukannya menggunakan data, yang merupakan array setiap baris set data, dan queryResponse, yang berisi metadata tentang kueri, seperti nama dan jenis kolom.

Anda juga dapat menggunakan metode bantuan yang disebut LookerCharts.Utils.htmlForCell untuk memberikan representasi HTML yang tepat dari titik data dalam sel tersebut. Metode ini otomatis menangani elemen seperti link lihat perincian, pemformatan, dan tindakan data:

  updateAsync: function(data, element, config, queryResponse, details, done) {

    // Grab the first cell of the data.
    var firstRow = data[0];
    var firstCell = firstRow[queryResponse.fields.dimensions[0].name];

    // Insert the data into the page.
    this._textElement.innerHTML = LookerCharts.Utils.htmlForCell(firstCell);

    // Always call done to indicate a visualization has finished rendering.
    done()
  }

Dengan demikian, langkah-langkah yang diperlukan untuk memiliki visualisasi kustom yang berfungsi telah selesai. Namun, penting untuk menyertakan metode penanganan error.

Menangani error

Kode updateAsync mengambil baris pertama data, tetapi error dapat terjadi jika kueri tidak menampilkan hasil atau tidak berisi dimensi apa pun.

Tanpa penanganan error, error JavaScript akan muncul di konsol browser, yang mungkin membingungkan pengguna saat diagram tidak dirender.

Diagram dapat menampilkan pesan error kustom jika mengalami masalah saat mencoba merender. Looker menambahkan dua fungsi ke objek visualisasi Anda: addError dan clearErrors. Anda dapat menggunakan fungsi ini untuk menampilkan pesan error yang akan dipahami oleh semua pengguna.

Karena ditambahkan ke objek visualisasi, fungsi ini tersedia dari konteks fungsi updateAsync Anda melalui objek this.

Anda dapat mengubah awal metode updateAsync untuk mendeteksi kondisi error, memberi tahu pengguna tentang masalah, dan keluar, alih-alih mencoba merender:

  updateAsync: function(data, element, config, queryResponse, details, done) {

    // Clear any errors from previous updates.
    this.clearErrors();

    // Throw some errors and exit if the shape of the data isn't what this chart needs.
    if (queryResponse.fields.dimensions.length == 0) {
      this.addError({title: "No Dimensions", message: "This chart requires dimensions."});
      // Always call done() before exiting early to avoid dashboard exports hanging
      done();
      return;
    }

    if (!data || data.length === 0) {
      this.addError({title: "No Data", message: "The query returned no results."});
      done();
      return;
    }

    // ... the rest of the update code here ...

Jika pengguna membuat kueri yang hanya berisi ukuran, mereka akan melihat pesan error yang serupa dengan berikut ini:

Rendering asinkron dan ekspor PDF

Dalam contoh "Halo Dunia" sebelumnya, fungsi done() dipanggil segera setelah DOM diperbarui. Pendekatan ini sesuai karena setelan innerHTML bersifat sinkron.

Namun, jika Anda menggunakan library pembuatan diagram seperti D3.js, Chart.js, atau React, rendering Anda kemungkinan bersifat asinkron. Jika Anda memanggil done() di bagian bawah skrip, Looker mungkin akan mengambil screenshot untuk ekspor PDF atau PNG sebelum diagram selesai digambar, yang dapat menghasilkan tile kosong.

Saat mengekspor dasbor, Looker menggunakan browser headless dan mengandalkan callback done() untuk mengetahui kapan waktu yang aman untuk mengambil screenshot.

Untuk memastikan diagram diekspor dengan benar, Anda harus mengaitkan callback done() ke peristiwa penyelesaian library dan menonaktifkan animasi selama ekspor menggunakan flag details.print.

Contoh berikut menunjukkan cara menangani rendering asinkron menggunakan D3.js:

  updateAsync: function(data, element, config, queryResponse, details, done) {
    this.clearErrors();

    // Check if Looker is exporting the chart to a PDF/PNG
    const isExport = details && details.print === true;

    // Clear previous elements
    this.svg.selectAll("*").remove();

    const circle = this.svg.append("circle")
      .attr("cx", 50)
      .attr("cy", 50);

    if (isExport) {
      // Instant render for exports. Draw the final state immediately with no transitions
      circle.attr("r", 40);

      // Tell Looker to take the screenshot right now
      done();
    } else {
      // If it's for the browser, start small and animate
      circle.attr("r", 0)
        .transition()
        .duration(1000)
        .attr("r", 40)
        .on("end", () => {
           // Tell Looker the animation is fully complete
           done();
        });
    }
  }

Jika Anda menggunakan React, pastikan Anda meneruskan callback done sebagai argumen ketiga ke fungsi render Anda sehingga Looker menunggu React untuk memasang komponen:

  this.chart = ReactDOM.render(
    <MyCustomChart data={data} />,
    element,
    done // Looker waits for React to finish
  );

Konfigurasi

Anda dapat mengizinkan pengguna menyesuaikan aspek visualisasi mereka.

Selain properti lain dari objek visualisasi, properti bernama options juga tersedia.

Anda dapat menggunakan properti ini untuk menentukan jenis opsi yang diperlukan diagram:

looker.plugins.visualizations.add({
  options: {
    font_size: {
      type: "string",
      label: "Font Size",
      values: [
        {"Large": "large"},
        {"Small": "small"}
      ],
      display: "radio",
      default: "large"
    }
  },
  // ... rest of visualization object ...

Contoh ini membuat opsi font_size yang ditampilkan sebagai tombol pilihan, sehingga pengguna dapat memilih antara ukuran font "kecil" dan "besar".

Menentukan properti options diperlukan untuk menambahkan opsi ke pemilih visualisasi.

Untuk menggunakan opsi ini dalam kode Anda, ingat bahwa dalam metode updateAsync ada parameter config. Parameter ini berisi opsi yang dipilih berikut:

updateAsync: function(data, element, config, queryResponse, details, done) {

Objek config terlihat seperti berikut:

{font_size: "large"}

Saat memperbarui diagram, Anda dapat memeriksa objek ini dan memberikan respons yang sesuai. Tambahkan pemeriksaan berikut di akhir metode update untuk menerapkan perubahan ukuran font:

if (config.font_size == "small") {
  this._textElement.className = "hello-world-text-small";
} else {
  this._textElement.className = "hello-world-text-large";
}

Anda juga harus memperbarui tag <style> yang ditambahkan dalam metode create untuk menentukan class CSS hello-world-text-small dan hello-world-text-large:

.hello-world-text-large {
  font-size: 72px;
}
.hello-world-text-small {
  font-size: 18px;
}

Karena fungsi updateAsync dipanggil setiap kali konfigurasi berubah, dan Looker otomatis menyimpan konfigurasi, ini adalah satu-satunya hal yang harus Anda lakukan untuk merespons setelan konfigurasi.

Langkah berikutnya

Anda dapat melihat kode sumber lengkap untuk visualisasi "Halo Dunia" ini di repositori GitHub open source Looker.

Untuk mengetahui informasi selengkapnya tentang fungsi tambahan, lihat Referensi API Visualisasi.