A API Looker Visualization é uma API JavaScript executada em um iframe em sandbox e hospedada no aplicativo Looker.
Você pode usar o mesmo código de visualização para mostrar uma visualização em qualquer lugar do Looker: Análises, Looks, painéis de dados, incorporações ou imagens renderizadas ou em PDF.
Cada visualização representa uma exibição de uma única consulta do Looker. O Looker executa a consulta e transmite os resultados ao código de visualização. O Looker também transmite um elemento DOM em que o código de visualização pode ser desenhado.
Requisitos
Antes de começar, verifique se você atende aos seguintes requisitos:
- É necessário ter algum conhecimento de JavaScript e desenvolvimento da Web.
- O acesso de administrador do Looker é necessário para criar e atualizar arquivos de manifesto do projeto LookML.
Criar uma visualização "Hello World"
Esta seção descreve como criar um script de visualização personalizado que mostra a primeira dimensão de uma consulta.
O resultado final precisa ser semelhante à imagem a seguir:

Configuração
Para desenvolver e testar uma visualização no Looker, você tem duas opções:
- Salve o código-fonte da visualização diretamente no projeto do LookML (recomendado).
- Hospede a visualização por HTTPS e aponte para ela no Looker.
Depois de configurar uma dessas opções, siga o exemplo nesta seção para criar hello_world.js.
Estrutura de código essencial
Para conferir o código-fonte final deste exemplo, consulte o repositório do GitHub.
Na pasta em que você está hospedando, crie um novo arquivo JavaScript em branco e nomeie-o como hello_world.js.
Para registrar uma nova visualização personalizada no Looker, chame a função looker.plugins.visualizations.add e transmita um objeto de visualização.
Esse objeto contém a definição da visualização e da UI de configuração.
O exemplo a seguir mostra o esqueleto de uma visualização com todas as propriedades necessárias preenchidas. Ele contém uma função create e uma função updateAsync em que você pode escrever o código de visualização:
looker.plugins.visualizations.add({
create: function(element, config) {
},
updateAsync: function(data, element, config, queryResponse, details, done) {
}
})
Esse código é uma visualização válida do Looker, mas ainda não é visual e aparece como uma caixa em branco.
Contexto
Considere a função create, que tem dois argumentos: element e config.
O Looker fornece um element, que é o
elemento DOM
que o Looker exige que você coloque sua visualização.
O Looker cria esse elemento e o torna do tamanho adequado. Você precisa colocar o conteúdo dentro dele.
A função create oferece a oportunidade de realizar a configuração inicial do elemento. Para este exemplo, você quer criar um gráfico semelhante à seguinte estrutura HTML:
<style>
/* custom styles for your chart */
</style>
<div class="hello-world-vis">
<div>Data Goes Here</div>
</div>
Usando JavaScript, você pode inserir elementos no elemento DOM para corresponder a essa estrutura.
O exemplo a seguir mostra essa função com mais detalhes adicionados:
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"));
},
Esse código adiciona CSS, cria o contêiner hello-world-vis e adiciona um div dentro dele.
O código também atribui this._textElement ao contêiner em que você quer renderizar. Isso é uma conveniência para que você não precise procurá-lo novamente mais tarde, quando o gráfico começar a ser renderizado.
A função create é um lugar conveniente para realizar tarefas de configuração que só precisam acontecer uma vez.
Renderização
Esta seção descreve como expandir o método updateAsync para visualizar dados. Esse método é chamado sempre que o gráfico precisa visualizar mudanças ou quando ocorre outro evento que possa afetar a renderização do gráfico (por exemplo, o gráfico é redimensionado ou uma opção de configuração muda).
Para este exemplo, você precisa encontrar apenas a primeira dimensão na primeira célula.
Você pode fazer isso usando data, que é uma matriz de cada linha do conjunto de dados, e queryResponse, que contém metadados sobre a consulta, como nomes e tipos de campos.
Você também pode usar um método auxiliar chamado LookerCharts.Utils.htmlForCell para fornecer a representação HTML adequada do ponto de dados nessa célula. Esse método processa automaticamente elementos como links de detalhamento, formatação e ações de dados:
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()
}
Isso conclui as etapas necessárias para ter uma visualização personalizada funcional. No entanto, é importante incluir um método para processar erros.
Tratamento de erros
O código updateAsync captura a primeira linha de dados, mas erros podem ocorrer se a consulta não retornar resultados ou não contiver dimensões.
Sem o tratamento de erros, um erro JavaScript aparece no console do navegador, o que pode confundir os usuários quando o gráfico não é renderizado.
Os gráficos podem mostrar mensagens de erro personalizadas se encontrarem problemas ao tentar renderizar. O Looker adiciona duas funções ao objeto de visualização: addError e clearErrors. Você pode usar essas funções para mostrar uma mensagem de erro que faça sentido para todos os usuários.
Como essas funções são adicionadas ao objeto de visualização, elas estão disponíveis no contexto da função updateAsync pelo objeto this.
Você pode modificar o início do método updateAsync para detectar uma condição de erro, notificar o usuário de um problema e sair em vez de tentar renderizar:
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 ...
Se o usuário criar uma consulta que contenha apenas medidas, ele vai receber uma mensagem de erro semelhante a esta:

Renderização assíncrona e exportações em PDF
No exemplo "Hello World" anterior, a função done() é chamada imediatamente após a atualização do DOM. Essa abordagem é adequada porque a configuração de innerHTML é síncrona.
No entanto, se você usar bibliotecas de gráficos como D3.js, Chart.js ou React, a renderização provavelmente será assíncrona. Se você chamar done() na parte de baixo do script, o Looker poderá capturar a captura de tela para uma exportação em PDF ou PNG antes que o gráfico termine de desenhar, o que pode resultar em um bloco em branco.
Quando o Looker exporta um painel de dados, ele usa um navegador sem interface gráfica e depende do callback done() para saber quando é seguro fazer uma captura de tela.
Para garantir que os gráficos sejam exportados corretamente, você precisa vincular o callback done() ao evento de conclusão da biblioteca e desativar as animações durante as exportações usando a flag details.print.
O exemplo a seguir mostra como processar a renderização assíncrona usando 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();
});
}
}
Se você usar o React, transmita o callback done como o terceiro argumento para a função de renderização para que o Looker aguarde a montagem dos componentes do React:
this.chart = ReactDOM.render(
<MyCustomChart data={data} />,
element,
done // Looker waits for React to finish
);
Configuração
Você pode permitir que os usuários personalizem aspectos da visualização.
Além das outras propriedades do objeto de visualização, uma propriedade chamada options está disponível.
Você pode usar essa propriedade para especificar o tipo de opções que o gráfico exige:
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 ...
Este exemplo cria uma opção font_size que é mostrada como botões de opção, permitindo que os usuários escolham entre tamanhos de fonte "pequeno" e "grande".
É necessário especificar a propriedade options para adicionar a opção ao seletor de visualização.
Para usar essa opção no código, lembre-se de que no método updateAsync há um parâmetro config. Esse parâmetro contém as seguintes opções selecionadas:
updateAsync: function(data, element, config, queryResponse, details, done) {
O objeto config é semelhante a este:
{font_size: "large"}
Ao atualizar o gráfico, você pode verificar esse objeto e responder de acordo. Adicione a seguinte verificação ao final do método de atualização para implementar mudanças no tamanho da fonte:
if (config.font_size == "small") {
this._textElement.className = "hello-world-text-small";
} else {
this._textElement.className = "hello-world-text-large";
}
Você também precisa atualizar a tag <style> adicionada no método create para definir as classes CSS
hello-world-text-small e hello-world-text-large:
.hello-world-text-large {
font-size: 72px;
}
.hello-world-text-small {
font-size: 18px;
}
Como a função updateAsync é chamada sempre que a configuração muda e o Looker salva automaticamente a configuração, é tudo o que você precisa fazer para responder às configurações.
Próximas etapas
Você pode conferir o código-fonte completo dessa visualização "Hello World" no repositório de código aberto do Looker no GitHub.
Para mais informações sobre funcionalidades adicionais, consulte a Referência da API Visualization.