# Visão geral

## O que é PocketBlocks?

**Openblocks + PocketBase = PocketBlocks.**

PocketBlocks é uma integração entre Openblocks e PocketBase.

Tradicionalmente, construir um aplicativo interno requer interações complexas de front-end e back-end com centenas ou milhares de linhas de código, sem mencionar o trabalho de empacotamento, integração e implantação. PocketBlocks reduz significativamente o trabalho que você precisa fazer para construir um aplicativo.

No PocketBlocks, tudo o que você precisa fazer é arrastar e soltar componentes pré-construídos ou autopersonalizados na tela What-You-See-Is-What-You-Get (WYSIWYG). PocketBlocks ajuda você a construir um aplicativo rapidamente e se concentrar na logíca do negócio.

## Por que escolher PocketBlocks?

* **Código aberto**: Torna suas ideias mais viáveis.
* **Alta escalabilidade**: Permite executar JavaScript em praticamente qualquer lugar onde você gostaria de personalizar seus processos de negócios e componentes de UI.
* **Design limpo**: Segue os princípios do Ant Design e suporta exibição em telas de diferentes tamanhos. Temos vários componentes de UI, com base nos quais você pode construir livremente painel de controle, painel de administração e sistema de gerenciamento de conteúdo (CMS).

## Como construir um aplicativo no PocketBlocks?

Construir um aplicativo interno leva basicamente 4 passos:

1. Conecte-se rapidamente à sua API Pocketbase usando o SDK.
2. Use componentes de UI pré-construídos ou personalizados pelo usuário para construir a UI do seu aplicativo.
3. Configure [manipuladores de eventos](/portugues-brasil/construcao-de-aplicativos/event-handlers) para acionar funções javascript, controlar componentes ou outras ações em reação às interações do usuário.
4. Visualize e compartilhe seu aplicativo com outras pessoas.


# Instalação

Neste artigo, você vai aprender como hospedar PocketBlocks em seu próprio servidor:

### Manualmente

* Baixe o binário do seu sistema operacional e arquitetura na [Página de Lançamento](https://github.com/pedrozadotdev/pocketblocks/releases);
* Execute o comando `./pocketblocks serve` no terminal;
* Acesse o [Aplicativo do PocketBlocks](http://localhost:8090) e crie o primeiro usuário administrador.

### Docker

* Salve o arquivo [docker-compose.yml](https://raw.githubusercontent.com/pedrozadotdev/pocketblocks/main/docker-compose.yml);
* Execute o comando `docker compose up -d` no terminal;
* Acesse o [Aplicativo do PocketBlocks](http://localhost:8080) e crie o primeiro usuário administrador.

### Fly.io

* Salve o arquivo [fly.toml](https://raw.githubusercontent.com/pedrozadotdev/pocketblocks/main/fly.toml);
* Edite o campo `app-name`;
* Execute o comando `flyctl launch` no terminal;
* Execute o comando `flyctl vol create data` no terminal;
* Execute o comando `flyctl deploy` no terminal;
* Acesse `https://<nome-do-seu-app>.fly.dev` e crie o primeiro usuário administrador.

{% hint style="info" %}
Lembre-se de que PocketBlocks usa o Openblocks como frontend. O diretório `pb_public` já está configurado, mas você pode usar o diretório `pbl_public` e todos os arquivos desse diretório serão servidos no caminho `<endereçoDoServidor>/pbl/`.
{% endhint %}


# Criando um novo aplicativo

## Criando um novo aplicativo da web

Clique em **Novo > Aplicativo** no canto superior direito da página inicial do Pocketblocks e vá para o editor do aplicativo. Você pode renomear o aplicativo no canto superior esquerdo do editor.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-f20605a3a9488c55c5b4da08648a9e8d1d2d01f7%2F01.gif?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Apenas **administradores** do espaço de trabalho podem criar aplicativos.
{% endhint %}

## Exportando e importando um aplicativo

### Exportando um aplicativo

Clique no nome do seu aplicativo e selecione **Exportar para JSON**, o aplicativo será exportado para um arquivo JSON.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-b9759dcae355becfd87fddc4d41c0abfcd818c41%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

### Importando um aplicativo

Você pode importar um aplicativo existente em formato JSON clicando em **Novo > Importar**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-0a3a380b4b7687048319896da66b48927f7fa01d%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>


# Editor de aplicativo

Dê uma rápida olhada no editor de aplicativos antes de começar

No PocketBlocks, o editor de aplicativos é onde você monta componentes, cria funções javascript para interagir com os dados do PocketBase e publica seus aplicativos. É composto por cinco áreas:

1. Barra de ferramentas
2. Canvas
3. Navegador de dados
4. Editor de consultas
5. Painel de componentes e propriedades

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-7e7804c9eb72a1c0cfdfd434e3309081c53d28d5%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

## Barra de ferramentas

A barra de ferramentas é composta por uma barra superior e uma barra lateral esquerda.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-7e7804c9eb72a1c0cfdfd434e3309081c53d28d5%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Na barra superior, você pode configurar seu aplicativo da seguinte forma:

* Alterar o nome do aplicativo
* Exportar para um arquivo JSON
* Controlar a visibilidade de outras áreas
* Compartilhe seu aplicativo
* Visualize e implante seu aplicativo
* Verifique as versões do histórico

Na barra lateral esquerda, algumas opções estão disponíveis como segue:

* Mostrar ou ocultar o **Navegador de dados**
* Defina o tamanho da tela e o tema do aplicativo
* Gerenciar scripts e estilos CSS
* Iniciar tutorial para editor de aplicativos
* Mostrar atalhos de teclado

## Canvas

O Canvas no centro do editor é onde você projeta e vê a UI geral. Arraste e solte componentes na tela, vincule-os a manipuladores de dados e eventos e monte-os para criar um aplicativo poderoso e agradável.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-4df0689fcfa18381dbbeb69a3f06215327305547%2F03.gif?alt=media" alt=""><figcaption></figcaption></figure>

Confira [Design UI do aplicativo](/portugues-brasil/construcao-de-aplicativos/design-app-ui) para práticas de layout de UI.

## Navegador de dados

O navegador de dados no painel esquerdo contém as seções **Consultas**, **Componentes** e **Globais**. Aqui você pode inspecionar os dados em uma estrutura em árvore. Por exemplo, para verificar os dados retornados de uma consulta ou componente específico, encontre seu item na seção pertencente e clique em<img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-be6600370e2b0c53146ca7c561cb7770b3d0cae6%2F04.png?alt=media" alt="" data-size="line">para expandir.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-100a4fea50166ca60ff2aa14a71268203c8556a0%2F05.gif?alt=media" alt=""><figcaption></figcaption></figure>

## Editor de consultas

O editor de consultas na parte inferior consiste em duas seções: lista de consultas (com as guias **Consultas** e **Metadados**) à esquerda e configurações de consulta (com **Geral**, **Notificação** e **Guias Avançadas**) à direita. Crie consultas para interagir com a API Pocketbase aqui.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-a9d6a0ab1834b35e302c6ad1f5220f3cb2f84cf6%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

Você pode acessar o SDK do Pocketbase através do objeto **window\.pb**.

## Painel de componentes e propriedades

O painel de componentes e propriedades está localizado à direita da janela. Arraste os componentes para a tela a partir da guia **Inserir** e edite as propriedades dos componentes na guia **Propriedades**.

![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-1950caf7abe4060c084dafe558fb7223b5e001de%2F07.png?alt=media) ![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-d374ffcb88b8da7e78dedd864e152a2d04216b68%2F08.png?alt=media)

Quando um componente é selecionado na tela, a guia **Propriedades** será ativada automaticamente e exibirá as propriedades desse componente.


# Manipuladores de eventos

No PocketBlocks, os manipuladores de eventos são responsáveis ​​por coletar e processar eventos de componentes e consultas e executar ações subsequentes. Por exemplo, para um componente **Botão**, você pode adicionar um manipulador de eventos para acionar a ação **Executar consulta** em resposta ao evento **Clique** do botão.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-355f17f35287dfb910f307a089f25096d0fb4966%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Defina manipuladores de eventos com sabedoria para fornecer uma experiência de usuário (UX) reativa e responsiva. Por exemplo, acionar uma consulta **retorna todos os dados** após o término da consulta de **inserção de dados** permite a atualização automática da tabela.

{% hint style="info" %}
Você pode adicionar quantos manipuladores de eventos desejar para um único componente ou consulta, e esses manipuladores de eventos serão executados simultaneamente.
{% endhint %}

## Eventos

### Eventos de componentes

Componentes diferentes têm eventos diferentes. Por exemplo, os componentes **Botão** possuem apenas um evento **Clique**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-f60f04771e931b181a0daa2b6f342cbf326332f8%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

Os componentes **Input** têm eventos **Mudar**, **Foco**, **Desfoque** e **Enviar**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-a98f05bd44cc8d9851a33c5ac3b152a36453bd8a%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### Consultar eventos

A execução de uma consulta pode resultar em sucesso ou falha, portanto, as consultas têm dois eventos: **Sucesso** ou **Falha**. Você pode adicionar manipuladores de eventos a consultas no Editor de consultas.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-90417f04a06ffe11d973ff0914f163d97e30f55d%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

## Ações

Existem várias ações de manipulador de eventos disponíveis no PocketBlocks para lidar com diferentes cenários. Defina-os na lista suspensa **Ação** em um manipulador de eventos.

![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-63ca9265154af55596c732d0699d0e6dcc4277e4%2F05.png?alt=media)

{% hint style="info" %}
Consulte [avançado](#advanced) nesta página para conhecer as configurações avançadas.
{% endhint %}

### Executar consulta

Acione a consulta selecionada.

![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-ee3b546ad05eb64467eb8e6af4a02554090132da%2F06.png?alt=media)

### Controlando Componentes

Para controlar um componente, selecione um componente na lista suspensa **Componente** e chame um de seus métodos na lista suspensa **Método**.

![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-17a7ccc19efe32d1b5fc72dcb18ed0cc20cd437e%2F07.png?alt=media)

### Definir estado temporário

Armazene dados em um [estado temporário](/portugues-brasil/construcao-de-aplicativos/write-javascript/temporary-state).

### Vá para um aplicativo

Navegue até um aplicativo PocketBlocks com consulta opcional ou parâmetros de hash.

| Parâmetro                  | Função                                                                                         |
| -------------------------- | ---------------------------------------------------------------------------------------------- |
| <p>Consulta de URL<br></p> | <p>Anexar <code>?key1=value1\&key2=value2...</code> ao URL do aplicativo a ser aberto.<br></p> |
| Hash de URL                | Anexe `#key1=value1&key2=value2...` ao URL do aplicativo a ser aberto.                         |

#### **Caso de uso**

No aplicativo **Lista de usuários**, clique em **Ver informações** para navegar até o aplicativo **Informações do usuário** e as informações detalhadas do usuário na linha selecionada serão exibidas.

1. O aplicativo **Lista de usuários** passa `{{currentRow.id}}` na linha da tabela como um parâmetro de consulta de URL para o aplicativo **Informações do usuário**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-1b2b8c47f9517c5ee875d0a822a6f5db852c4a41%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>

2. O campo URL da variável global do aplicativo **Informações do usuário** resolverá automaticamente o URL solicitado pelo aplicativo. Neste caso, o valor de `url.query` é `{"id":3}`, então a consulta recuperará as informações do usuário correspondentes via `{{url.query.id}}`. Veja a figura abaixo.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-a266d2ca87d725e21bcd4cfdc8c30e0ea59e4fb1%2F09.png?alt=media" alt=""><figcaption></figcaption></figure>

### Ir para URL

Navegue para um URL externo.

![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-9ff1a09dcd1e1f951297e5555de3bb360e42dec8%2F10.png?alt=media)

### Mostrar notificação

Mostre uma notificação flutuante de mensagem informativa, de sucesso, de aviso ou de erro.

![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-6b25995fa580812164f243f112aba47dfd1e1d40%2F11.png?alt=media)

### Copiar para área de transferência

Copie um valor para a área de transferência.

![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-702abbe61107557fc62a6d2ae4bab49a9a0211c7%2F12.png?alt=media)

### Exportar dados

Exporte dados em um determinado tipo de arquivo (TXT, JSON, CSV e Excel).

![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-365ce2d597f8b986b037e15bbdd43433c9764a00%2F13.png?alt=media)

## Avançado

### Execute apenas quando

A ação só pode ser acionada sob uma condição especificada. Configure a condição de execução de um manipulador de eventos na opção **Executar somente quando** e, em seguida, o manipulador de eventos será executado somente quando esta condição for avaliada como `true`.

### Debounce e throttle

**Debounce** e **Throttle** reduzem a frequência de acionamento da ação.

#### **Debounce**

Debounce atrasa uma ação. Uma vez definido o tempo de debounce, a ação não será executada imediatamente após o evento até que o tempo de debounce passe. Se o evento ocorrer novamente antes do término do tempo, o tempo de debounce será cronometrado novamente. Por exemplo, um componente de entrada aciona uma consulta quando o usuário altera o texto. Se a execução da consulta for cara e você não quiser executá-la depois que cada caractere for digitado, você poderá atrasar a execução da consulta definindo o tempo de rejeição. Então a consulta só será executada depois que o usuário terminar de digitar.

#### **Throttle**

Throttle permite que uma ação aconteça apenas uma vez durante um período de tempo especificado. Por padrão, cada evento desencadeia uma ação, mas às vezes executar uma ação pode custar caro. Por exemplo, você define um identificador de evento para acionar a ação **Executar consulta** para atualizar dados em resposta ao evento **Clique**, mas acha que essa consulta é muito cara para ser executada, então você pode definir um tempo de aceleração para permitir que a consulta seja executada apenas uma vez em um determinado período.


# Escrevendo JavaScript


# Escrevendo JavaScript por {{ }}

Ao construir aplicativos no PocketBlocks, você pode usar JavaScript (JS) para acessar e transformar dados de objetos, incluindo componentes, consultas e parâmetros globais. Ao escrever JavaScript dentro da caixa de entrada da propriedade do componente, configurações de coluna da tabela, etc., lembre-se sempre de colocar todo o seu código JS entre chaves duplas, como `{{'olá, ' + usuarioAtual.nome}}`.

## Acessando dados

Os objetos têm nomes globalmente exclusivos, como `entrada1`, `consulta1` e `tabela1`. Você pode consultar as propriedades dos objetos em seu aplicativo por código JS.

### Acessando dados em um objeto

PocketBlocks oferece suporte para acessar os dados em um objeto usando notação de ponto (`nomeDoObjecto.nomeDaChave`). Por exemplo, `{{informacoesDoUsuario.selectedRow.nome}}` acessa o valor `nome` na linha atualmente selecionada da **Tabela** `informacoesDoUsuario`.

Ao escrever JS em `{{ }}` para acessar valores em um objeto, adicione um `.` após o nome do objeto para acionar um menu de sugestão automática caso você não tenha certeza sobre as propriedades ou métodos integrados dos objetos.

**Exemplo**

Este GIF mostra como a notação de ponto aciona um menu de sugestão automática e exibe as propriedades de `tabela1`.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-3b47b6b9935cfc67c6d87947da04a7f2d8f037a5%2F01.gif?alt=media" alt=""><figcaption></figcaption></figure>

### Acessando dados em um array

Você pode acessar os valores em um array por índice. O índice sempre começa em 0, então você pode usar `array[0]` para acessar o primeiro elemento do array.

**Exemplo**

A propriedade **Data** do componente **Tabela** é uma matriz de objetos. Este GIF mostra como acessar o valor de `primeiro_nome` no primeiro elemento do array **data** em `tabela1`.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-bdbf3a16a06e4d33da454e5207602e4ee4058611%2F02.gif?alt=media" alt=""><figcaption></figcaption></figure>

## Transformando dados

Você pode aproveitar funções JS integradas e bibliotecas de terceiros em `{{ }}` para transformar dados, como operações `filter()`, `map()` e `reduce()`.

**Exemplos**

Colocando texto em caixa baixa.

```javascript
{
  {
    entrada1.value.toLowerCase();
  }
}
```

Alterar formato de data

```javascript
{
  {
    moment(tabela1.selectedRow.coluna).format("DD/MM/YYYY");
  }
}
```

Retornar o nome dos resultados da consulta.

```javascript
{{consulta1.data.map(i => i.nome)}}.
```

## Restrições

O código JS em `{{ }}` deve ser um código de linha única, como `.map()` ou `.reduce()` combinado com uma função de seta ou um operador ternário.

**Exemplos**

```javascript
{
  {
    consulta1.data.id.length;
  }
} // ✅ para referenciar um valor
{
  {
    consulta1.data.map((linha) => linha.id);
  }
} // ✅ .map() + função arrow
{
  {
    num1 > num2 ? num1 : num2;
  }
} // ✅ ternário
```

Os seguintes exemplos de código JS são ilegais em `{{ }}`.

```javascript
{
  {
    // ❌ você não pode escrever código como este em {{ }}
    const lista = consulta1.data;
    const listaFiltrada = lista.filter((isso) => isso.valor > 10);
    return listaFiltrada;
  }
}
```

Se você deseja orquestrar múltiplas linhas de JavaScript, PocketBlocks oferece suporte para escrever esse código em [transformadores](/portugues-brasil/construcao-de-aplicativos/write-javascript/transformers).

```javascript
// códigos dentro de um transformador
if (seletor.value === "1") {
  return "Opção 1";
}
if (seletor.value === "2") {
  return "Opção 2";
}
return "Opção 3";
```

## Ver dados

Os dados das consultas podem ser complicados e aninhados em casos reais. A visualização de dados fornece a estrutura detalhada dos dados em objetos e ajuda a entendê-los melhor. Antes de acessar ou transformar dados, pode ser necessário primeiro visualizar os dados e sua estrutura. PocketBlocks oferece três maneiras de visualizar dados.

### Ver resultado da consulta

Depois de executar uma consulta dentro do editor de consultas, clique no botão **Executar**. O resultado da consulta é exibido no formato mostrado abaixo.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-8a79058dbcca6c1787164beb0954d4f06ca473a0%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### Visualizando dados no navegador de dados

O navegador de dados localizado no painel esquerdo exibe todos os dados dentro do seu aplicativo. Você pode clicar no nó para expandir e visualizar a estrutura de dados.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-efc32ec4439a4803b4a408e8c47cf0e837b13b8f%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

### Visualizando em tempo real

Ao configurar propriedades ou escrever código JS dentro de um editor, você pode visualizar o resultado avaliado em tempo real em uma caixa abaixo do seu editor.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-9ca18ca65ef0389aac995890c6f897a6c7ae1fcc%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>


# Consulta JavaScript

Há casos em que você deseja orquestrar operações, por exemplo, após acionar duas consultas, deseja combinar e armazenar seus resultados em um estado temporário e, em seguida, abrir um modal. Este processo pode ser complicado ao encadear vários manipuladores de eventos e certamente não pode ser feito em uma linha de código em `{{ }}`. É aí que entra a consulta JavaScript (JS). Ela libera a capacidade de interagir com componentes e consultas escrevendo consultas JS complexas para realizar as seguintes operações:

* Interagir com componentes da UI
* Acionar consultas
* Acessar bibliotecas JS de terceiros
* Personalizar funções

O exemplo a seguir é para você entender rapidamente o que é consulta JS e como ela funciona.

## Retorna dados

Use a sintaxe `return` para retornar o resultado. Por exemplo, o código a seguir retorna `3`.

```javascript
return Math.floor(3.4);
```

O resultado retornado também pode ser um objeto [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). Por exemplo, `query2.run()` retorna um objecto promise.

```javascript
return query2.run();
```

{% hint style="info" %}
A instrução `return` não é necessária para cenários onde você deseja omitir resultados.
{% endhint %}

## Acessando dados

Use consultas JS para acessar dados em seu aplicativo. Observe que não há necessidade de usar a notação `{{ }}`.

```javascript
var data = [input1.value, query1.data, fileUpload.files[0].name];
```

## Controlando Componentes

Em consultas JS, você pode usar métodos expostos por componentes para interagir com componentes de UI em seu aplicativo. Tal operação não é suportada pelo código JS embutido em `{{}}`.

```javascript
// defina o valor de input1 como "Olá"
input1.setValue("Olá");
```

{% hint style="warning" %}
O método `input1.setValue()` (ou outros métodos componentes) é assíncrono e retorna um objeto [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). Acessando `input1.value` imediatamente após definir o valor de `input1` não retorna o valor atualizado.
{% endhint %}

## Executando consulta

### `run()` método e retornos de chamada

Execute o método `run()` para executar outras consultas, por exemplo:

```javascript
return consultaPorNome.run(); // execute uma consulta e ela retornará uma Promise
```

O valor de retorno de `query.run()` é uma promise, então você pode anexar retornos de chamada para lidar com o resultado ou erro bem-sucedido.

```javascript
return consultaPorNome.run().then(
  (data) => {
    // após a consulta ser executada com sucesso
    return "olá, " + data.user_fullname;
  },
  (error) => {
    // após a consulta ser executada com falha
    // use a função de mensagem integrada para exibir uma mensagem de erro
    message.error("Ocorreu um erro ao buscar o usuário: " + error.message);
  }
);
```

### Passando parâmetros

Você pode passar parâmetros no método `run()` para dissociar a implementação da consulta de seus parâmetros.

```javascript
query.run({
    parametro1: valor1,
    parametro2: valor2,
    ...
});
```

## Declarando uma função

Você pode declarar funções dentro de uma consulta JS para melhor legibilidade.

```javascript
// Se o primeiro número é um múltiplo do segundo número
function eMultiplo(num1, num2) {
  return num1 % num2 === 0;
}

// Chame a biblioteca do moment para retornar a data atual
function dataAtual() {
  return moment().format("DD/MM/YYYY");
}
```

## Adicionando scripts pré-carregados

PocketBlocks oferece suporte à importação de bibliotecas JS de terceiros e à adição de código JS predefinido, como a adição de métodos ou variáveis ​​globais para reutilização em **nível de aplicativo** ou **nível de espaço de trabalho**. Você pode encontrar as configurações no nível do aplicativo em ⚙️ > **Outros** > **Scripts e estilo**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-b9de9f654a7ee43bc6a0964505614b9c2fb0da74%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Para nível de espaço de trabalho, acesse ⚙️ **Configurações** > **Avançado**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-247f4d3c507eb744bad2414b828ee8a25cf93d79%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

Na guia **JavaScript**, você pode adicionar código JavaScript pré-carregado para definir métodos e variáveis ​​globais e reutilizá-los em seu aplicativo. Para importar bibliotecas, consulte [Usando biblioteca de terceiros](/portugues-brasil/construcao-de-aplicativos/write-javascript/use-third-party-libraries).

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-170b902259471f5bd095aac65d5be5e80a1d8235%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-814df3bf6a2c8983b8bdf0ae4d5818680a420d03%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

## Restrições

Por motivos de segurança, diversas variáveis ​​globais e funções de **window** estão desabilitadas no PocketBlocks. Por favor, reporte ao nosso [GitHub](https://github.com/pedrozadotdev/pocketblocks) se você encontrar algum problema.


# Transformadores

Os transformadores são projetados para transformação de dados e reutilização de seu código JavaScript multilinha. Os dados de consultas ou componentes podem não atender às suas necessidades em cenários de negócios. Além disso, você pode usar o mesmo bloco de código várias vezes em um aplicativo. Nesses casos, um transformador é o que você precisa.

Comparado com o código embutido em `{{ }}`, o transformador suporta blocos de código multilinha. E, diferentemente da consulta JavaScript, o transformador foi projetado para realizar operações somente leitura, o que significa que você não pode acionar uma consulta ou atualizar um estado temporário dentro de um transformador.

## Começando

Clique em **+ Novo > Transfromer** em um editor de consultas para criar um transformador.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-2d5f20d4dc84c73647ef5257d365c0af4b3b538a%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Em seguida, escreva seu código JS no transformador. Você pode clicar em **Visualizar** para obter o valor de retorno e acessá-lo por `nomeDoTransformador.value` em seu aplicativo.

No exemplo a seguir, `transformador1` usa os dados de classificação por estrelas em `avaliacao1` para calcular uma pontuação.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-558da7dcf200fe832f95eb529c21b4d2fdc3d34f%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
`{{ }}` não é permitido dentro de um transformador ou consulta JS. `{{ }}` é usado apenas para fins de expressão JS de linha única, enquanto um transformador ou consulta JS é para múltiplas linhas de código JS.
{% endhint %}

## Casos de uso

### Transformação de data e hora

Use o método `moment().format()` para transformar formatos de data/hora. O exemplo a seguir converte o valor de data/hora de `tempo_inicial` retornado por `consulta1` para o formato `DD/MM/YYYY`.

```javascript
return consulta1.data.map((isso) => {
  return {
    ...isso,
    tempo_inicial: moment(it.tempo_inicial).format("DD/MM/YYYY"),
  };
});
```

### Classificando dados da consulta

Use o método `_.orderBy()` fornecido por [lodash](https://lodash.com/) para classificar os dados. O exemplo a seguir retorna `consulta1.data` classificado pela coluna `quantidade` em ordem crescente.

```javascript
return _.orderBy(consulta1.data, "quantidade", "asc");
```

### Juntando duas consultas

O código de exemplo abaixo mostra como unir os resultados da consulta de `usuarios` e `pedidos` usando o ID do usuário.

```javascript
const usuarios = consultarUsuarios.data;
const pedidos = consultarPedidos.data;
return usuarios.map((usuario) => ({
  ...usuario,
  pedidos: pedidos.find((pedido) => pedido.clienteId === usuario.id),
}));
```

## Operações somente leitura

Somente operações somente leitura são permitidas dentro de um transformador. Isso significa que você não pode definir valores de componentes ou estados temporários, nem acionar consultas. Para essas operações, use consultas JavaScript.

Por exemplo, você não pode chamar o método `setText()` de um componente de texto em um transformador.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-b3e8cb516f20a41a129de4633a9570d8b4bb8d3d%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

Em vez disso, chame o método `setText()` em uma consulta JavaScript não reporta nenhum erro.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-ce903980ea2557602727ff9d8683f0df128561f7%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

Em outro exemplo, o transformer`ordernador1` visa classificar os dados de `consultarUsuarios` por `primeiro_nome`, mas o método `sort()` pode alterar os dados originais, então ocorre um erro.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-903b25440681539f13b8d3d9310ffae3403c1808%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

Neste caso, use o método `_.orderBy()` fornecido por [lodash](https://lodash.com/).

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-760e3a4024a421ac677aebce30b5f725da3fb3cb%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>


# Estado temporário

Você pode usar o estado temporário para armazenar e fazer referência a dados locais em um aplicativo. Cada vez que você carrega ou atualiza um aplicativo, o valor do estado temporário é redefinido.

## Cenários de casos de uso

Os estados temporários podem ajudar nos seguintes cenários:

* Para rastrear os valores temporários de uma variável quando o usuário interage com seu aplicativo.
* Para armazenar seus dados apenas em operação sem persistir em um banco de dados.
* Para funcionar como uma propriedade temporária quando propriedades integradas no PocketBlocks (como `{{tabela.selectedRow}}` e `{{seletor.value}}`) não suportam seu caso de uso.

  <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>Para armazenar e acessar dados em aplicativos no seu espaço de trabalho, use o localStorage.</p></div>

## Crie um estado temporário

Clique em **+ Novo** e selecione **Estado temporário** no editor de consultas.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-af21e42d8590fe1c47d9e4aa657773e4100e2ae5%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Você pode renomear o estado temporário e definir um valor inicial.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-43b528a5e6775200e05e0e5eda0f68f53b9d65e3%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

## Definindo valores de estado

O estado temporário oferece métodos `setValue()` e `setIn()` para definir ou alterar seu valor, que podem ser chamados em consultas JavaScript.

Use `setValue()` para alterar o valor diretamente.

```javascript
//state.setValue(value: any)
state.setValue(3);
state.setValue(input1.value);
```

Quando o valor inicial de um estado temporário é um objeto, use `setIn()` para alterar o valor em um caminho especificado.

```javascript
// valor inicial de estado2 da seguinte forma:
{
    garota: {
        nome: "Lucia",
        idade: 18,
        cidade: {
            nome: "Nova Iorque"
        }
     }
     garoto: {
         nome: "Bob",
         idade: 21,
         cidade: {
             nome: "Los Angeles"
         }
     }
}
//Para alterar o valor em um caminho especificado
//estado.setIn(caminho, qualquerValor)
//caminho: uma matriz de chaves ou índices. Somente o último item do caminho será alterado.
estado2.setIn(['garota','cidade'],{nome:'Seatle'})
estado2.setIn(['garoto','idade'],18)


// Para definir o valor da matriz de valor, você pode usar
// valor inicial = ["olá", "mundo"]
estado2.setIn([1],"fulano") // isso resultará em ["olá", "fulano"]
```

Você também pode chamar esses dois métodos em [manipuladores de eventos](/portugues-brasil/construcao-de-aplicativos/event-handlers). Selecione **Definir estado temporário** como ação e escolha o método sob demanda.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-33aabacaf95efc0bb82e1c8a2002df398845671c%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

## Exemplo: Incremento de um contador

Neste exemplo, o contador rastreia o número de cliques no botão. Cada vez que o usuário clica no botão, o número no componente de texto aumenta em um.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-27cd7081b78fc5d80f7892a488ed66474931d17e%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

Crie um contador de incremento nas seguintes etapas:

1. Adicione um componente de botão `botao1` e um componente de texto `texto1`.
2. Crie um estado temporário `estado1`, defina seu valor inicial como `0`. Vincule `{{estado1.value}}` como o texto de exibição de `texto1`.

   <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-8d74b984f133658d234f13e698b9ec1153988783%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>
3. Adicione um manipulador de eventos para `botao1`. Selecione a ação **Definir estado temporário** e o método **setValue**, e então defina `{{estado1.value+1}}` como o valor.

   <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-80a8e3ad7472721bf453ae298bbe476ffd984091%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>
4. Clique no botão, você pode ver que o valor de `texto1` aumenta em um cada vez que você clica.

   <figure><img src="https://github.com/internoapp/pocketblocks/blob/main/docs/pt-br/.gitbook/assets/build-apps/write-javascript/temporary-state/07.png" alt=""><figcaption></figcaption></figure>

Você também pode obter o mesmo resultado usando consultas JavaScript:

1. Adicione uma nova consulta e selecione **Executar código JavaScript**.
2. Escreva a consulta JavaScript com este código e configure-a para ser invocada manualmente:\
   `estado1.setValue(estado1.value + 1)`
3. Adicione um manipulador de eventos `botao1` para executar `consulta1`.

   <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-e3fc9c462e0b2e860a365acece23ab566166d70f%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>

Agora clique no botão **Incrementar contador**, você deverá ver o mesmo resultado acima.


# Respondedor de dados

Ao construir um aplicativo, você pode definir eventos para os componentes para ouvir as alterações de determinados dados. Por exemplo, para um componente **Tabela**, os eventos integrados para a alteração da propriedade `selectedRow` incluem "Alteração de seleção de linha", "Alteração de filtro", "Alteração de classificação" e "Alteração de página".

No entanto, faltam eventos semelhantes para algumas alterações de dados, como alterações de estados temporários, transformadores ou resultados de consultas. Os respondedores de dados são projetados para esses casos e permitem ouvir e responder a qualquer alteração nos dados.

{% hint style="info" %}
Os eventos para respondedores de dados são mais gerais do que os eventos que escutam alterações de dados, como alteração de conteúdo, alteração de seleção de linha, etc.
{% endhint %}

## Ouça as alterações de dados

No editor de consultas, clique em **+ Novo** e selecione **Respondedor de dados** para criar um novo respondedor de dados.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-0cb25108b83cb9110814341ecf8e4000c7cd6af7%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Você pode definir os dados que o respondedor de dados escuta. Ele suporta todos os tipos de formatos de dados, incluindo número, string, array e objeto JS. No exemplo a seguir, qualquer alteração de valor no componente **Texto** aciona uma notificação global.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-eb7510b411ad7e90a46d356da92f75d3e2b4c3e7%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

Se os dados estiverem em formato de array ou objeto JS, a alteração dos dados de qualquer subelemento acionará o evento configurado. Por exemplo, os dados de `dataResponder2` são um objeto JS, que escuta dois componentes **Entrada de Texto** no aplicativo. A alteração de dados de qualquer componente aciona a mesma notificação global.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-3eae4971204c4d314d3b0f327f836336ef87ca67%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

## Respondendo ações

Para obter informações detalhadas, vá para [Manipuladores de eventos](/portugues-brasil/construcao-de-aplicativos/event-handlers) > [Ações](/portugues-brasil/construcao-de-aplicativos/event-handlers#actions).


# Funções JavaScript integradas

## utils - funções utilitárias

### utils.openUrl()

Abra um URL.

```javascript
// Sintaxe
utils.openUrl( url: string, options?: { newTab:  boolean = true } )
```

| Parâmetros     | Descrição                                                                                                                        |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| <p>url<br></p> | Obrigatório. Um valor **Texto** que especifica o URL a ser aberto. Deve começar com *http\://* or *https\://*.                   |
| newTab         | Opcional. **Booleano** valor que, quando **True**, especifica que o URL será aberto em uma nova guia. O valor padrão é **True**. |

```javascript
// Exemplo: Abre google.com em uma nova aba.
utils.openUrl("https://www.google.com", { newTab: true });
```

### utils.openApp()

Abra um aplicativo PocketBlocks.

```javascript
// Sintaxe
utils.openApp( applicationId: string, options?: { queryParams?: {"chave":"valor"}, hashParams?: {"chave":"valor"}, newTab: true } )
```

| Parâmetro                                                     | Descrição                                                                                                                                                                                                                                                                                                                                      |
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p>appId<br></p>                                              | <p>Obrigatório. Um valor <strong>Texto</strong> que especifica o ID do aplicativo a ser aberto.</p><p><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-00e5a0852de1eb4fadd5a387886f6c0b78d3a2c1%2F01.png?alt=media" alt="" data-size="original"></p> |
| queryParams: {'chave1':'valor1',chave2:'valor2',...}          | Opcional. Um **Objeto** que especifica parâmetros de consulta a serem transmitidos ao aplicativo. Os parâmetros de consulta são adicionados ao URL do aplicativo na forma de ?*chave1=valor1\&chave2=valor2&...*                                                                                                                               |
| <p>hashParams：{'chave1':'valor1',chave2:'valor2',...}<br></p> | Opcional. Um **Object** que especifica parâmetros de hash a serem transmitidos ao aplicativo. Os parâmetros hash são adicionados ao URL do aplicativo na forma de *#chave1=valor1\&chave2=valor2&...*                                                                                                                                          |
| newTab                                                        | Opcional. Um valor **Booleano** que, quando **True**, especifica o URL deve ser aberto em uma nova guia. O valor padrão é **True**.                                                                                                                                                                                                            |

```javascript
// Exemplo: Abre um aplicativo PocketBlocks em uma nova guia.
utils.openApp("632bddc33bb9722fb888f6c0", { newTab: true });

// Exemplo: Abre um aplicativo PocketBlocks e passa o parâmetro "id".
utils.openApp("632bddc33bb9722fb888f6c0", {
  queryParams: { id: tabela1.selectedRow.id },
});
```

### utils.downloadFile()

Baixa um arquivo contendo os dados especificados.

```javascript
// Sintaxe
utils.downloadFile(data: any, fileName: string, options?: {
  fileType?: string,
  dataType?: "url" | "base64"
} )
```

| Parâmetro | Descrição                                                                                                                                                                                                    |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| data      | Obrigatório. Um **Texto** ou **Objeto** que especifica os dados para download de consultas, componentes, transformadores, etc.                                                                               |
| fileName  | Obrigatório. Um valor **Texto** que especifica o nome do arquivo para download.                                                                                                                              |
| fileType  | Opcional. Um valor **Texto** que especifica o tipo de arquivo para download. Todos os [tipos MIME](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) são suportados. |
| dataType  | Opcional. Um valor **Texto** que especifica o tipo de dados: "url" ou "base64".                                                                                                                              |

```javascript
// Exemplo: baixe os dados base64 de um componente de arquivo como um arquivo PNG denominado dados-do-usuario.
utils.downloadFile(file1.value[0], "dados-do-usuario", {
  fileType: "png",
  dataType: "base64",
});

// Exemplo: Faça download dos resultados de consulta1 como um arquivo XLXS denominado dados-do-usuario.
utils.downloadFile(consulta1.data, "dados-do-usuario", { fileType: "xlsx" });
// ou desta forma:
utils.downloadFile(consulta1.data, "dados-do-usuario.xlsx");

// Exemplo: Faça download dos resultados de consulta1 como um arquivo PDF denominado dados-do-usuario.
utils.downloadFile(consulta1.data, "dados-do-usuario", {
  fileType: "pdf",
  dataType: "base64",
});
```

### utils.copyToClipboard()

Copie um texto para a área de transferência.

```javascript
// Sintaxe
utils.copyToClipboard( text: string )
```

| Parâmetro | Descrição                                                                |
| --------- | ------------------------------------------------------------------------ |
| text      | Obrigatório. Um valor **Texto** que especifica o conteúdo a ser copiado. |

```javascript
// Exemplo: Copie o conteúdo do componente de entrada para a área de transferência.
utils.copyToClipboard(input1.value);
```

## message – notificação global

Use métodos `message` para enviar uma notificação de alerta global, que é exibida na parte superior da tela e dura 3 segundos por padrão. Cada um dos quatro métodos a seguir oferece suporte a um estilo de exibição exclusivo.

```javascript
// message.info( text: string, options?: {duration: number = 3 } )
message.info("Por favor confirme suas informações", { duration: 10 });
// message.success( text: string, options?: {duration: number = 3 } )
message.success("A consulta foi executada com sucesso", { duration: 10 });
// message.warn( text: string, options?: {duration: number = 3 } )
message.warn("Aviso", { duration: 10 });
// message.error( text: string, options?: {duration: number = 3 } )
message.error("Consulta foi executada com erro", { duration: 10 });
```

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-bb0706b4f7bca60aa3f80cb617faed39d4702c66%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

## localStorage

Use métodos `localStorage` para armazenar e gerenciar dados de pares de valores-chave localmente, que não são redefinidos quando o aplicativo é atualizado e podem ser acessados ​​em qualquer aplicativo dentro do espaço de trabalho usando `localStorage.values`.

| Método                             | Descrição                             |
| ---------------------------------- | ------------------------------------- |
| setItem(*key: string, value: any*) | Armazena um par de chave valor.       |
| removeItem(*key: string*)          | Remove um par de chave valor.         |
| clear()                            | Limpa todos os dados no localStorage. |

### localStorage.values

Você pode acessar qualquer par de chave valor no armazenamento local usando `localStorage.valores.` em consultas JavaScript.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-9934ba4438d67b2f02e8224eb9f52c148be0e230%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

Inspecione os dados em localStorage em **Globals** no navegador de dados.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-ca0a38274adc7a5e702e2a487d6cf8a25ed62548%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

### localStorage.setItem()

Armazena um par de chave valor.

```javascript
// Sintaxe
localStorage.setItem(key: string, value: any)

// Exemplo
localStorage.setItem("pedido", seletor1.value)
```

### localStorage.removeItem()

Remove um par de chave valor.

```javascript
// Sintaxe
localStorage.removeItem(key: string)

// Exemplo
localStorage.removeItem("pedido")
```

### localStorage.clear()

Limpa todos os dados no localStorage.


# Uso de bibliotecas de terceiros

Todo desenvolvedor aprende um dos princípios mais importantes da engenharia de software no início de sua carreira: DRY (Don’t Repeat Yourself). O uso de bibliotecas de terceiros pode economizar seu tempo, pois você não precisa desenvolver a funcionalidade que a biblioteca oferece. PocketBlocks fornece algumas bibliotecas integradas de terceiros para usos comuns, e você pode importar manualmente outras bibliotecas sob demanda.

## Bibliotecas integradas

PocketBlocks fornece algumas bibliotecas JavaScript integradas para uso.

| Biblioteca               | Documentação                                               | Versão                     |
| ------------------------ | ---------------------------------------------------------- | -------------------------- |
| lodash                   | <https://lodash.com/docs/>                                 | 4.17.21                    |
| moment                   | <https://momentjs.com/docs/>                               | 2.29.3                     |
| uuid                     | <https://github.com/uuidjs/uuid>                           | 8.3.2（Support v1/v3/v4/v5） |
| numbro                   | <https://numbrojs.com/format.html>                         | 2.3.6                      |
| papaparse(Papa)          | <https://www.papaparse.com/docs>                           | 5.3.2                      |
| PocketBase SDK(pb)       | <https://pocketbase.io/docs/client-side-sdks>              | 0.21.3                     |
| TanStack QueryClient(qc) | <https://tanstack.com/query/v5/docs/reference/QueryClient> | 5.44.0                     |

## Importando manualmente bibliotecas de terceiros

PocketBlocks suporta a configuração de JavaScript pré-carregado e bibliotecas que podem estar no **nível do aplicativo** ou no **nível do espaço de trabalho**.

* **Bibliotecas em nível de aplicativo** são carregadas somente no aplicativo onde definido. Além disso, o aplicativo A não pode usar bibliotecas configuradas para o aplicativo B.
* **Bibliotecas no nível do espaço de trabalho** serão carregadas quando você abrir qualquer aplicativo no seu espaço de trabalho. Todos os aplicativos podem acessar essas bibliotecas. Pode haver um certo impacto no desempenho do aplicativo, especialmente quando você tem funções JavaScript complexas que não estão sendo usadas em todos os aplicativos.

**Dicas que você deve saber antes de configurar bibliotecas:**

* Bibliotecas externas são carregadas e executadas no navegador.
* Bibliotecas somente NodeJS não são suportadas.
* URLs de bibliotecas externas precisam oferecer suporte a vários domínios.
* A exportação da biblioteca deve ser configurada diretamente no objeto window, variáveis ​​globais como `var xxx = xxx` não têm efeito.
* As bibliotecas externas são executadas em um ambiente sandbox restrito e as seguintes variáveis ​​globais não estão disponíveis:

  <mark style="background-color:yellow;">`parent`</mark>

  <mark style="background-color:yellow;">`document`</mark>

  <mark style="background-color:yellow;">`location`</mark>

  <mark style="background-color:yellow;">`chrome`</mark>

  <mark style="background-color:yellow;">`setTimeout`</mark>

  <mark style="background-color:yellow;">`fetch`</mark>

  <mark style="background-color:yellow;">`setInterval`</mark>

  <mark style="background-color:yellow;">`clearInterval`</mark>

  <mark style="background-color:yellow;">`setImmediate`</mark>

  <mark style="background-color:yellow;">`XMLHttpRequest`</mark>

  <mark style="background-color:yellow;">`importScripts`</mark>

  <mark style="background-color:yellow;">`Navigator`</mark>

  <mark style="background-color:yellow;">`MutationObserver`</mark>

Agora vamos pegar **cowsay** como exemplo e importá-lo no nível do aplicativo e no nível do espaço de trabalho.

* Página do GitHub: <https://github.com/piuccio/cowsay>
* Link da Biblioteca: <https://unpkg.com/cowsay@1.5.0/build/cowsay.umd.js>

### No nível do aplicativo

Navegue até a página de configurações e clique no sinal de mais **+** na guia **Biblioteca JavaScript**. Cole o link **cowsay** e clique em **Adicionar novo**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-efa0e9d94a4b923fca1a7e60a69129a79bd4c576%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Crie uma consulta JS e insira o código.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-7b4159f6aa9ecf480a18f11809278b6c39863433%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

Você pode obter o mesmo resultado chamando o método `cowsay.say()` no valor do componente de texto.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-983783686b7e8dcba1845c8925a7dbda15c91c26%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

Observe que a biblioteca cowsay é importada no nível do aplicativo e você não pode usá-la em nenhum outro aplicativo em seu espaço de trabalho.

### No nível do espaço de trabalho

Vá para a página inicial do PocketBlocks, selecione **Configurações** > **Avançado** e clique em **Adicionar** na guia **Biblioteca JavaScript**. Cole o link da biblioteca JS de terceiros e clique em **Adicionar novo** para adicioná-la ao seu espaço de trabalho. As bibliotecas instaladas podem ser acessadas de qualquer aplicativo em seu espaço de trabalho.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-15db33a7fa64f2210f7c27deb5153943476b2aa9%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>


# Guias de Componentes


# Lista de opções

Um menu suspenso garante uma entrada fácil e sem erros do usuário, oferecendo uma lista de opções possíveis. PocketBlocks suporta a implementação de listas de opções usando componentes como **Seletor** e **Seletor Mútiplo**. Você pode configurar uma lista de opções manualmente ou mapeando dados de suas fontes de dados.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-fa478a3ded8dbc5080636e789acfdb79e1201f84%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

## Propriedades

Cada lista de opções possui quatro propriedades.

* **Rótulo**: o texto da opção exibido aos usuários
* **Valor**: o identificador exclusivo da opção
* **Desativado**: desativa a opção (o valor padrão é `false`)
* **Oculto**: oculta a opção (o valor padrão é `false`)

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-9a2d3d0ff354754fdfc265140ca63d399662494c%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Quando mais de uma opção em uma lista utiliza o mesmo valor, apenas a primeira opção é válida e, portanto, exibida.
{% endhint %}

## Modo manual

Em **Básico** > **Manual**, clique em **+ Adicionar** para criar uma nova opção. Selecione uma opção para configurá-lo manualmente. Você pode clicar em `···` para **Duplicar** ou **Excluir** uma opção e arrastar `⋮⋮` para organizar sua posição.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-03142b278b4923047bd088a735be13043b839075%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

Verifique o valor da opção selecionada em **Componentes** no navegador de dados. Por exemplo, quando **Nova York** é selecionado, você pode encontrar o valor da string `"1"` para **localizacaoSelecionada**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-9305c141912c192f2c099034287c24ed0dfd118e%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

O modo manual é recomendado para estes cenários:

* Gerenciável e enumerável manualmente.
* Usado por apenas um componente.
* Os dados não vêm de fontes de dados.

## Modo mapeado

Quando você tiver dados da lista de opções provenientes de fontes de dados, transformadores ou estado temporário, poderá usar o **Modo Mapeado**. Em **Básico** > **Mapeado**, insira sua matriz de fonte de dados na caixa **Dados** usando código JavaScript (JS). Uma lista de opções será mapeada automaticamente a partir deste array. Por exemplo, acesse informações da universidade via `{{universidade.dado}}`. Cada item na matriz de resultados contém `pais`, `paginas_web`, `codigo` e `nome`.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-6626d935e8babeb656a64429c2c908c06ca961ef%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

Você pode referenciar o valor de qualquer campo de uma opção através de `item` e seu índice `i`, começando em 0. No exemplo a seguir, o **Rótulo** de cada opção é o `nome` da universidade, o **Valor** é `web_page`, e aqueles que contêm um parêntese de abertura `(` em seus nomes estão desativados. O valor padrão é definido como `paginas_web` do primeiro item usando `{{universidade.dado[0] .paginas_web}}`. Observe que o valor padrão de uma lista de opções deve ser um elemento do array **Valor**, mas não do array **Rótulo**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-88182c7047eba7fe0cd49af9fd090f3db271f426%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

Verifique o valor da opção selecionada em **Componentes** no navegador de dados. Por exemplo, quando "Ahi Evran University" é selecionado, seu valor de string `[\"http://www.ahievran.edu.tr/\"]` é exibido.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-42816198a31d64ef9dc7f66f5236237c840494ee%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>


# Exibição em lista

O componente Exibição em lista serve para você exibir linhas de dados. Funciona como um contêiner: você pode inserir outros componentes nele e vincular dados a esses componentes.

O componente **Exibição em lista** exibe linhas de dados. Semelhante a Formulário, Modal e Drawer, também é um componente semelhante a um contêiner que pode conter outros componentes ou módulos. Para dados de exibição em lista, primeiro vincule os dados a um componente **Exibição em lista** e configure as regras de nomenclatura para os itens. Em seguida, você projeta a exibição da primeira linha arrastando e soltando os componentes, e esse layout será aplicado a todos os itens desse componente.

A seguir está uma demonstração da **Exibição em lista**, exibindo parte dos MELHORES LIVROS DE 2021 de[Goodreads](https://www.goodreads.com/choiceawards/best-books-2021):

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-91b66edb1a7a6b899afed0ad5c1598594adef4c8%2F01.gif?alt=media" alt=""><figcaption></figcaption></figure>

Arraste e solte o **Exibição em lista** na tela. Cada item contém uma **Imagem**, um **Texto** e um componente de **Avaliação**. Você pode atualizar a exibição de todo o componente **Exibição em lista** configurando o layout da primeira entrada.

Clique no componente **Imagem** para ver a fonte da imagem padrão.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-0d76d350c550482ba95a4e06cf6961083bff2bcc%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

O componente **Exibição em lista** recupera dados de uma matriz JSON de objetos e exibe um componente **Imagem**, **Texto** e **Avaliação** para cada entrada. Você também pode passar os resultados da consulta para uma **Exibição em lista**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-b28fda2639f66f65a338092fe81c1796c2774386%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

## Vinculando dados

Os dados de um componente **Exibição em lista** aceitam dois tipos de valores: número e matriz.

* Número: os números são processados ​​como contagem de linhas e nenhum dado válido é passado para o componente **Exibição em lista**.
* Array: O comprimento de um array é passado como contagem de linhas e cada entrada no array é processada como um objeto JS no formato JSON, correspondendo a uma linha no componente **Exibição em lista**. Por exemplo, os dados a seguir contêm duas linhas de dados, cada uma contendo quatro campos: `avaliacao`, `titulo`, `url` e `cover`.

```json
[
  {
    "avaliacao": "9.2",
    "titulo": "The Shawshank Redemption",
    "url": "https://www.imdb.com/title/tt0111161/",
    "cover": "https://m.media-amazon.com/images/M/MV5BMDFkYTc0MGEtZmNhMC00ZDIzLWFmNTEtODM1ZmRlYWMwMWFmXkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_UY67_CR0,0,45,67_AL_.jpg"
  },
  {
    "avaliacao": "9.2",
    "titulo": "The Godfather",
    "url": "https://www.imdb.com/title/tt0068646/",
    "cover": "https://m.media-amazon.com/images/M/MV5BM2MyNjYxNmUtYTAwNi00MTYxLWJmNWYtYzZlODY3ZTk3OTFlXkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_UY67_CR1,0,45,67_AL_.jpg"
  }
]
```

Você pode visualizar os dados detalhados sobre o componente **Exibição em lista**, seus itens, propriedades, etc., no navegador de dados.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-b402a4c8aad35da5e4e09ce71135caf894252fd7%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-32530fd8afda0dd7aa665bb0aba711a2143d5b91%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

## Exibir dados em componentes internos

Depois de vincular dados válidos ao componente **Exibição em lista** e projetar seus componentes internos, você pode adicionar dados a esses componentes. **Exibição em lista** suporta variáveis ​​locais `currentItem` e `i`. Observe que você só precisa alterar os dados da primeira linha, e as mesmas configurações são aplicadas às outras linhas automaticamente.

{% hint style="info" %}
Você pode vincular um endereço URL estático ao componente **Imagem** para exibição de imagens; e como esse endereço URL é estático, a mesma imagem aparece em todas as linhas.
{% endhint %}

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-979603a2c59fb4e3c4c3bd46e72f60425a36658a%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

## Nomeando os itens

Você pode definir os nomes dos índices dos itens e os nomes dos dados dos itens. Isto é útil ao incorporar uma lista em outra lista. Por exemplo, você pode definir o índice de uma lista como `i` e o aninhado interno `j` para evitar conflito de nomenclatura.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-17eb20ad5a7e7ac1727c511591d03fad9ec3facf%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>

### Nome do índice do item

Por padrão, o índice do item é denominado `i`, referindo-se ao índice dos dados da lista e começando do zero. Além de usar `i` como números, você também pode usar `i` para acessar dinamicamente os dados dos resultados da consulta.

Por exemplo, para acessar o campo `nome_do_livro` da tabela `ficcao` no componente **Texto**, escreva o seguinte código.

```javascript
{
  {
    getAllFictions.data[i].nome_do_livro;
  }
}
```

Em seguida, você poderá ver os nomes dos livros de ficção exibidos no **Exibição em lista** por ordem de índice.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-b3b05d6b1208396c6f90c771b2d067cc55b9f0da%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>

### Nome dos dados do item

Por padrão, você pode referenciar o valor de cada item em uma lista usando a variável `currentItem`. Por exemplo, para exibir um número de série mais o nome do livro, escreva o seguinte código no valor `texto1`.

```javascript
{{i+1}}. {{currentItem.nome_do_livro}}
```

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-2c5175b05636ee1e30bcdb08ab7a6601e0f4d006%2F09.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Erros de dependência circular ocorrem quando você faz referência aos dados de uma linha por `listView.items[i]` de um componente dentro de um componente **Exibição em lista**. Recomenda-se usar tal referência somente fora da lista.
{% endhint %}

## Paginação

### Pulo rápido

Alterne "Mostrar pulo rápido" ou defina seu valor como `true` para permitir que seus usuários acessem rapidamente a página especificada.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-69f2526e7cc83ec413559dc3e2bafd8dfc90c99f%2F10.png?alt=media" alt=""><figcaption></figcaption></figure>

### Tamanho da página

Você pode configurar se deseja permitir que seus usuários personalizem quantos itens serão exibidos em uma única página ativando ou desativando o "Mostrar botão de alteração de tamanho" ou definindo seu valor em JS. Quando desativado, você pode definir o tamanho de página padrão.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-d08cfc0aa055b032166318577ad28900be988fb1%2F11.png?alt=media" alt=""><figcaption></figcaption></figure>

Se ativado, você poderá configurar vários tamanhos de página para serem selecionados pelos usuários.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-80b32ab743ab32945e7a049e7aedcdec38001fdf%2F12.png?alt=media" alt=""><figcaption></figcaption></figure>

### Contagem total de linhas

Por padrão, a contagem total de linhas de um componente **Exibição em lista** é o número de itens de dados atuais. Você também pode inserir um valor de uma consulta. Por exemplo, `{{consulta1.data[0].countador}}`.

## Referenciar itens fora da lista

**Exibição em lista** oferece suporte à exposição de dados de componentes internos com o campo **Itens**. Você pode inspecionar o **Navegador de dados** no painel esquerdo.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-c1d97560e602a04ff715fdef42aaddffbeb8d58b%2F13.png?alt=media" alt=""><figcaption></figcaption></figure>

Por exemplo, arraste um componente **Entrada de Texto** para **Exibição em lista** e, em seguida, você poderá referenciar o valor do componente **Avaliação** em componentes fora do **Exibição em lista** pelo código a seguir.

```javascript
{
  {
    listView1.items[0].rating1.value;
  }
}
```

<figure><img src="https://github.com/internoapp/pocketblocks/blob/main/docs/pt-br/build-apps/.gitbook/assets/build-apps/component-guides/list-view/14.png" alt=""><figcaption></figcaption></figure>


# Menu lateral

No PocketBlocks, **Drawer** é uma barra lateral sobreposta para exibir informações ou realizar operações, sem interromper o fluxo de trabalho na janela principal.

O exemplo a seguir cria um carrinho de compras usando uma gaveta.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-44b6735b27a655318d844b4cbee727c44bd09cb3%2F01.gif?alt=media" alt=""><figcaption></figcaption></figure>

## Layout

Quando inserida pela operação de arrastar e soltar, um **Drawer** flutua no lado direito (por padrão) da janela principal. Em seguida, você pode adicionar componentes ao **Drawer** de acordo com suas necessidades. No modo de edição de um **Drawer**, outros componentes na tela não são editáveis.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-9c2897af1112decde715ae9966ab0ad30c456c2a%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Quando um Drawer é fechado, você pode reabri-lo clicando no rótulo correspondente na guia **Modais** no painel esquerdo.
{% endhint %}

### Posição

Na aba **Propriedades**, você pode definir a posição do Drawer. A posição padrão é o lado direito da janela principal.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-60c86dbce46602c951a86dffb6a00f4ff97d9412%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### Redimensionando

Na aba **Propriedades**, você pode definir a largura do drawer em pixels ou porcentagem. Observe que a altura de um drawer é igual à da janela principal e não é personalizável.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-8c2defeb4c6b8f0fc8fbd6be1a6a0c4f950c3e07%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

## Eventos

Você pode fazer referência a um drawer no código JS em qualquer lugar do seu aplicativo ou chamá-lo por meio de uma ação de "componente de controle" em **Propriedades** > **Interação** > **Manipuladores de eventos**.

As seções a seguir orientam você sobre como abrir e fechar um drawer clicando em um botão em um aplicativo de compras online.

### Acionando openDrawer

Normalmente, em um aplicativo, você aciona a abertura de um drawer por meio de um evento como clicar em um botão. Por exemplo, abrir um drawer para exibir o carrinho de compras é implementado nas etapas a seguir.

1. Adicione um botão e renomeie-o como `irParaCarro`.
2. Defina o manipulador de eventos do botão. Selecione "Componente de controle" como **Ação** e selecione o componente "carrinho" e o método "openDrawer". Todas essas configurações são salvas automaticamente.

   <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-7821071c8dfc0d19ff1872edf12e3c9d4a810c85%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>
3. Clique no botão `irParaCarro` e o drawer vinculado(carrinho) será aberto.

### Acionando o fechamento do drawer

Acionar "closeDrawer" é semelhante a acionar "openDrawer". Ao configurar o manipulador de eventos, selecione o método "closeDrawer". Por exemplo, fechar um drawer que exibe o carrinho de compras é implementado nas etapas a seguir.

1. Adicione um botão e renomeie-o como `voltarShopping`.
2. Defina o manipulador de eventos do botão. Selecione "Componente de controle" como **Ação** e selecione o componente "carrinho" e o método "closeDrawer". Todas essas configurações são salvas automaticamente.

   <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-4f602ff0373e1773e634a0c6eddadccd5ed27fc7%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>
3. Clique no botão “Continuar Comprando” e o drawer vinculado (carrinho) é fechado.


# Imagem

Use o componente **Imagem** para apresentar informações nos seus aplicativos de maneira vívida. PocketBlocks suporta a adição de uma imagem via URL e dados codificados em base64.

## URL

Arraste o componente **Image** para a tela ou para um **Container**. Clique no componente **Imagem** e a guia **Propriedades** será exibida à direita. Você pode definir o URL para exibir uma imagem.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-c1a89d777a1c25e9db7c3383f008cf6d133a1634%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

## Dados codificados em Base64

Você também pode inserir uma imagem por meio de dados codificados em base64. Certifique-se de que a fonte da imagem codificada comece com `data:image/FORMATODAIMAGEM;base64,` ou simplesmente `data:image;base64,`.

{% hint style="warning" %}
Não esqueça da vírgula no final do prefixo:

<mark style="background-color:yellow;">`data:image/FORMATODAIMAGEM;base64`</mark><mark style="background-color:yellow;">**`,`**</mark> <mark style="background-color:yellow;">`OS_DADOS_DA_SUA_IMAGEM_EM_BASE64`</mark>

<mark style="background-color:yellow;">`data:image;base64`</mark><mark style="background-color:yellow;">**`,`**</mark><mark style="background-color:yellow;">`OS_DADOS_DA_SUA_IMAGEM_EM_BASE64`</mark>
{% endhint %}

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-15d74088204212f3856431e58bd13ef5378a3e06%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

### Demo: carreguando e exibindo uma imagem

Um caso de uso comum para exibição de imagens base64 seria combinar um componente **Upload de arquivo** com um componente **Imagem**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-b87fb138d00f2f2b1eb0e76d32f09d0259849f5f%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

Aqui está o código JS que concatena o prefixo com os dados codificados em base64 do arquivo enviado por meio de `arquivo1.value[0]`.

```javascript
{
  {
    "data:image/jpeg;base64," + arquivo1.value[0];
  }
}
```

## Definindo visualização de clique para uma imagem

Ative **Suporte a visualização de clique** na guia **Propriedades** para permitir que os usuários visualizem a imagem em tamanho real. Passe o mouse sobre a imagem e você verá **👁 Visualização**. Então, você pode clicar para visualizar.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-981bae349627378e062905c0be29681c7e77ec2e%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

## Definindo o estilo de uma imagem

Em **Propriedades** > **Estilo**, altere a cor da borda e defina o **Raio da borda** em pixels ou em porcentagem.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-0699ab5484a4d9c9fed8c80390acb1f71d646755%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>


# Gráficos

Tabelas e gráficos são representações visuais de dados usados ​​para simplificar informações complexas e torná-las mais fáceis de entender. Eles podem ajudar a destacar insights importantes e fornecer um resumo rápido de dados que, de outra forma, seriam difíceis de interpretar. Os gráficos vêm em diferentes formatos, como gráficos de barras, gráficos de linhas, gráficos de pizza, gráficos de dispersão e muito mais, cada um adequado para diferentes tipos de dados e finalidades analíticas.

PocketBlocks permite inserir vários formatos de tabelas e gráficos em seus aplicativos para satisfazer suas necessidades em diferentes casos de uso.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-70b97ee672992652a80e1287c2ddf5046da63584%2F01.gif?alt=media" alt=""><figcaption></figcaption></figure>

## Modo UI

### Formato de dados

No modo UI, o componente **Gráfico** oferece suporte à apresentação de dados armazenados como uma matriz de objetos JS. Cada campo de objeto corresponde a uma coluna em formato tabular. Os objetos na matriz a seguir contêm três campos: `data`, `fruta` e `contador`.

```json
[
  { "data": "2022-03-01", "fruta": "apple", "contador": 4 },
  { "data": "2022-03-01", "fruta": "banana", "contador": 6 },
  { "data": "2022-04-01", "fruta": "grape", "contador": 10 },
  { "data": "2022-04-01", "fruta": "apple", "contador": 3 },
  { "data": "2022-04-01", "fruta": "banana", "contador": 2 }
]
```

Você também pode usar o código JS em `{{}}` para fazer referência a dados de outros componentes ou consultas ou para transformar dados para atender a necessidades específicas.

Por exemplo, o resultado da consulta `colsulta1` é o seguinte.

```json
{
  "data": [
    "2022-03-01",
    "2022-03-01",
    "2022-04-01",
    "2022-04-01",
    "2022-04-01"
  ],
  "fruta": ["apple", "banana", "grape", "apple", "banana"],
  "contador": [4, 6, 10, 3, 2]
}
```

Você pode transformá-lo usando o transformador `transformador1` com o seguinte código JS.

```javascript
let datas = query1.data.data;
let frutas = query1.data.fruta;
let contadores = query1.data.contador;
let resultado = [];
for (let i = 0; i < datas.length; i++) {
  resultado.push({ date: datas[i], fruta: frutas[i], count: contadores[i] });
}
return resultado;
```

Em seguida, referencie o valor do transformador `{{transformador1.value}}` como dados para o gráfico.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-c5f78c77975e75dd06a8eeb3690f35a1a06dff57%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

### Tipo de Gráfico

PocketBlocks oferece suporte a quatro tipos de gráficos: gráfico de barras, gráfico de linhas, gráfico de dispersão e gráfico de pizza. Você pode selecionar o tipo de gráfico em **Propriedades** > **Dados** > **Tipo de gráfico**. Você também pode personalizar o layout e o estilo do seu gráfico na guia **Propriedades**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-e9e1f265ee8c3b79146b21fd6a9c913a69b11677%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### Eixo X

Gráficos de barras, gráficos de linhas e gráficos de pizza mapeiam valores para variáveis ​​categóricas. Assim, nesses gráficos, o eixo X geralmente mostra dados não numéricos – por exemplo, data ou departamento.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-900a9cd6fe91d0742f1c62eae8ed93f35c6e4bb3%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

Por padrão, o PocketBlocks detecta automaticamente os dados do eixo X e seu tipo. Você também pode selecionar manualmente um entre "Eixo de categoria", "Eixo de valor", "Eixo de tempo" ou "Eixo de registro". Para obter informações detalhadas, consulte [tipo de eixo X](https://echarts.apache.org/en/option.html#xAxis.type).

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-e372b134378c0a0898bd8d50daca49b5cf93e3ee%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

### Série de gráficos

Na maioria dos tipos de gráficos, a **Série de gráficos** (eixo Y) apresenta valores numéricos para as categorias no eixo X. Por padrão, PocketBlocks preenche todos os campos numéricos no eixo Y. Você pode ocultar campos desnecessários em **Propriedades** > **Série de gráficos**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-2fdc87184f9009da81a29108e8de32589fec1d60%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

## Echarts em JSON

Além dos gráficos integrados, você também pode plotar seus dados com o [Apache ECharts](https://echarts.apache.org/en/index.html), uma biblioteca de visualização JS de código aberto. Você só precisa preencher o campo **Configuração** > **Opção** no formato JSON. Para informações detalhadas, consulte a [documentação do ECharts](https://echarts.apache.org/en/option.html#title) e os [exemplos do ECharts](https://echarts.apache.org/examples/en/index.html).

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-50ce7d33d5414be7e1fd94a00603e6634f576cd7%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>

Se precisar de mais opções de configuração para gráficos, crie uma issue no [Github](https://github.com/pedrozadotdev/pocketblocks/issues).


# Carregamento de arquivo

## Fundamentos

Você pode personalizar as propriedades dos componentes de upload de arquivo no painel direito, como texto exibido, tipos de arquivo e tipo de upload.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-9477baa0cc92ad40f14b400e047ff9bc48a8e7b6%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

### Tipo de arquivo

Você pode inserir uma série de strings para restringir os tipos de arquivos a serem carregados. O valor padrão do tipo de arquivo está vazio, o que significa que nenhuma limitação é predefinida. Cada valor de string em uma matriz de tipo de arquivo especificada deve ser um [especificador de tipo de arquivo exclusivo](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#unique_file_type_specifiers) em um dos os seguintes formatos.

* Uma extensão de nome de arquivo válida que não diferencia maiúsculas de minúsculas, começando com um caractere de ponto final ("."), como `.png`, `.txt` e `.pdf`.
* Uma string válida em [formato MIME](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) sem extensão.
* String `audio/*` indicando "qualquer arquivo de áudio".
* String `video/*` indicando "qualquer arquivo de vídeo".
* String `image/*` indicando "qualquer arquivo de imagem".

Por exemplo, quando o valor do tipo de arquivo é `[".pdf", ".mp4", "image/*"]`, você pode fazer upload de arquivos PDF, arquivos MP4 e qualquer tipo de arquivo de imagem.

### Tipo de upload

Você pode decidir se deseja fazer upload de um único arquivo, de vários arquivos ou de um diretório.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-9f66e6420a5047c59444144cc36032c113f85526%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

### Exibir arquivos enviados

Ative ou desative **Mostrar lista de upload** para exibir ou ocultar a lista de arquivos enviados. Você também pode definir essa propriedade por meio do código JS. Por padrão, seu valor é “verdadeiro”.

A lista de upload apresenta os nomes de todos os arquivos carregados em ordem cronológica. Você também pode acessar o nome dos arquivos enviados através da propriedade `files[index].name`. Ao passar o mouse sobre um arquivo, o ícone 🗑️ aparece e você pode clicar nele para excluir o arquivo correspondente.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-2f5313fa437c165c4aafff215aaa18506e330d03%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### Analisar arquivos

Alterne **Analisar arquivos** e o PocketBlocks tentará analisar a estrutura de dados do arquivo carregado em objetos, matrizes ou strings. Você pode acessar o resultado analisado através da propriedade `parsedValue`. PocketBlocks oferece suporte à análise de arquivos Excel, JSON e CSV. O resultado da análise de outros tipos de arquivos é `null`.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-5bcbe9c9162064e0b52505435d229f4d72900d99%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

## Validação

Na aba de validação, você pode configurar quantos arquivos podem ser carregados, bem como o tamanho mínimo e máximo de um único arquivo a ser carregado.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-dfb5c5c64ecb6ba70db53e06392dc21f59b9377d%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

### Máximo de arquivos

Quando o tipo de upload é "Múltiplo" ou "Diretório", você pode definir **Máximo de arquivos** para limitar o número máximo de arquivos a serem carregados. Se o número de arquivos a serem carregados exceder esse limite, os arquivos carregados mais recentemente substituirão os mais antigos.

### Tamanho do arquivo

Você pode definir o tamanho mínimo e máximo dos arquivos para upload, usando unidades KB, MB, GB ou TB. A unidade padrão para tamanho de arquivo é byte. Quando o tamanho do arquivo enviado exceder o limite, você verá um alerta global.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-d4458ed294bf11fc27f23a4e9dbc41eb7c91e838%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

### Acessando os arquivos enviados

Os arquivos carregados por meio do componente de upload de arquivo são armazenados na memória cache do navegador em formato de string **codificado em base64**. Para armazenar esses arquivos em fontes de dados, você precisa criar consultas para conectar-se a bancos de dados ou APIs. Você pode visualizar as propriedades dos arquivos enviados no navegador de dados no painel esquerdo ou acessar os nomes das propriedades em `{{}}` ou Consultas JS via código JS. As propriedades comumente usadas são as seguintes.

* `value`: Uma lista do conteúdo dos arquivos enviados, codificados em base64.
* `files`: Uma lista de metadados dos arquivos enviados, incluindo `uid`, `name`, `type`, `size` e `lastModified`.
* `parsedValue`: Uma lista do valor dos arquivos analisados.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-f1ec0b7ce2fb3d777d45f24c437381bc1191b60d%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>


# Componente customizado

No PocketBlocks, você pode projetar componentes personalizados usando a biblioteca React.js para satisfazer necessidades específicas ao construir seu aplicativo. O componente personalizado pode ser estático ou dinâmico, mas requer codificação.

## Pré-requisitos

* Bom entendimento de como construir um aplicativo em PocketBlocks.
* Familiarizado com HTML/CSS/JS e a biblioteca React.js.

## Fundamentos

Arraste um **componente personalizado** para a tela. Por padrão, PocketBlocks adiciona uma caixa de título, uma caixa de texto e dois botões, conforme mostrado abaixo. Você pode modificar **Dados** e **Código** no painel **Propriedades** para adaptá-los de acordo com suas necessidades.

{% hint style="info" %}
Clique na borda em vez da área interna para selecionar um **Componente personalizado** e exibir suas configurações de propriedade.
{% endhint %}

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-4ebe459d87bacbeecada740113acd657b23c4498%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

### Dados

**Dados** armazena informações em pares de valores-chave, fornecendo uma interface para o **componente personalizado** interagir com dados externos. Por exemplo, você pode referenciar dados do **componente personalizado** em outros componentes do seu aplicativo por meio de `nomeDoComponenteCustomizado.model` ou passar dados de outros componentes para o **componente personalizado**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-fffcc9fbe23f3e17d387d2b4756b7e3c6195687e%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

### Código

Por padrão, PocketBlocks define o objeto `model` e duas funções `execultarConsulta` e `atualizarModel`.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-cae4eab9f486e6493cfc680571de1887f9e8679e%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

* `executarConsulta` é uma função que aceita um nome de consulta em formato texto. Por exemplo, `executarConsulta(model.consulta)`.
* `atualizarModel` é uma função que aceita um único argumento do tipo objeto. O argumento passado para `atualizarModel` será mesclado com os dados do **Componente customizado**.

## Implementação

Todo o código do seu **componente personalizado**, incluindo HTML, CSS e JavaScript, é armazenado na caixa **Código** no painel **Propriedades**. Quando seu aplicativo for executado, o componente personalizado será incorporado em um elemento [iframe](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe). Para facilitar a interação entre o **Componente personalizado** e outros componentes do seu aplicativo, o PocketBlocks oferece uma API para você por meio de objetos globais. A definição do tipo e a descrição dos objetos são as seguintes.

```typescript
interface PBL {
  // Assine a alteração de dados
  // Quando os dados mudam, o manipulador será acionado
  // O valor retornado é a função de cancelamento de assinatura
  subscribe(handler: SubscribeHandler): () => void;
  // Função do componente React HOC que aceita um componente React
  // Retorna um novo componente que contém propriedades: runQuery, model, updateModel
  connect(Component: ComponentType<any>): ComponentType;
  // Execute a consulta especificada
  runQuery(queryName: string): Promise<void>;
  // Atualizar dados
  updateModel(patch: any): Promise<any>;
}

interface SubscribeHandler {
  (data: IDataPayload): void;
}

interface IDataPayload {
  model: any;
}
```

O exemplo a seguir é o mínimo de código que um componente personalizado requer para funcionar.

```javascript
<div id="react"></div>
<script type="text/babel">
    const MyCustomComponent = ({ runQuery, model, updateModel }) => (
        <p>Olá, mundo!</p>
    );
    const ConnectedComponent = pbl.connect(MyCustomComponent);
    ReactDOM.render(<ConnectedComponent />,
document.getElementById("react"));
</script>
```

## Interação de dados

### Passando dados do aplicativo para o componente personalizado

Por exemplo, para passar o texto em uma caixa de entrada para um componente personalizado, você pode usar a sintaxe `{{}}` para referenciar dados deste componente **Texto**. Observe que você também pode fazer referência a dados de consultas da mesma maneira.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-09d51ab907885c396e7422b4c82ea97402891764%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

Abaixo está o código para este exemplo.

```javascript
<div id="root"></div>

<script type="text/babel">

  const { Button, Card, Space } = antd;

  const MyCustomComponent = ({ runQuery, model, updateModel}) => (
    <Card title={"Olá, " + model.nome}>
        <p>{model.texto}</p>
        <Space>
          <Button
            type="primary"
            onClick={() => runQuery(model.query)}
         >
            Acionar consulta
          </Button>
          <Button
            onClick={() => updateModel({ texto: "Também estou de bom humor!" })}
          >
          Atualizar dados
          </Button>
      </Space>
    </Card>
  );

  const ConnectedComponent = pbl.connect(MyCustomComponent);

  const root = ReactDOM.createRoot(document.getElementById("root"));
  root.render(<ConnectedComponent />);

  </script>
```

### Passando dados do componente personalizado para o aplicativo

Por exemplo, para exibir determinado texto do **Componente personalizado** em um componente **Input** no aplicativo, você pode definir o valor de `custom1.model.nome` como o valor padrão de `entrada1`. A notação de ponto `custom1.model.nome` acessa o nome do **componente personalizado**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-af9ff85cda451bd27c595d6cafb2e3cdceec9bde%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

### Acionando consulta do componente personalizado

Por exemplo, dada a tabela `usuarios` que exibe informações de todos os usuários, você deseja filtrar os dados com base no texto inserido em um **Componente personalizado**. Além disso, a operação de filtro é acionada clicando em um botão dentro do mesmo **Componente personalizado**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-b6d5e2998f3916fced84f976b4f965e122cca85d%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

De acordo com o requisito, o **componente personalizado** contém um componente **Input** e um componente **Botão**. Você também pode adicionar um componente **Texto** para fornecer contexto aos usuários do seu aplicativo. Quando um usuário insere na caixa de texto, por exemplo "Lor", e a seguir clica no botão de pesquisa, a tabela apresenta apenas as entradas em que o campo "Nome" que contém "Lor".

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-19256a2ff9c368215ab3a759d29794c913c3b2a6%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>

Para implementar esse **componente personalizado**, primeiro você cria a consulta `filtrarUsuario` para acessar os dados do componente personalizado e configura-o para ser executado por invocação manual.

```javascript
return usuarios.value.filter((u) =>
  u.name.includes(custom1.model.pesquisa || "")
);
```

Em seguida, você importa a biblioteca "antd" e utiliza os componentes **Button**, **Input**, **Card** e **Space**. Por fim, mais uma configuração para cada componente dentro do **Componente personalizado**:

* Configure o método `updateModel` para executar e atualizar os dados do **Componente personalizado** quando o texto no componente **Input** for alterado.
* Acionar a consulta `filtrarUsuario` pelo método `runQuery` quando o botão **Pesquisar** for clicado.

```javascript
<style type="text/css">
  body {
    padding: 5px;
  }
</style>

<link rel="stylesheet" type="text/css" href="https://unpkg.com/antd@4.21.4/dist/antd.min.css"/>

<script type="text/javascript" src="https://unpkg.com/antd@4.21.4/dist/antd.min.js" ></script>

  <div id="root"></div>

<script type="text/babel">

  const { Button, Card, Input, Space } = antd;

  const MyCustomComponent = ({ runQuery, model, updateModel}) => (
    <Card title={"Olá, " + model.nome + " filtra dados para você!"}>

        <Space>
      <Input
          value={model.search}
          onChange={e => updateModel({ pesquisa: e.target.value})}
          placeholder="Nome"
        />
          <Button
            type="primary"
            onClick={() => runQuery("filtrarUsuario")}
         >
            Search
          </Button>

      </Space>
    </Card>
  );

  const ConnectedComponent = pbl.connect(MyCustomComponent);

  const root = ReactDOM.createRoot(document.getElementById("root"));
  root.render(<ConnectedComponent />);

</script>
```


# Uso de Markdown

PocketBlocks oferece suporte ao uso da linguagem de marcação leve Markdown para formatar textos em seu aplicativo, como alterar o tamanho da fonte, inserir código e adicionar uma lista. Você também pode incorporar texto formatado em HTML no Markdown para obter mais opções de estilo.

Use Markdown nos componentes **Texto** e **Tabela**.

* **Texto**: Use Markdown para o texto de entrada.

  <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-c07a890503c0c484350cfc51332230e7e2c48392%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>
* **Tabela**: Use Markdown para tipo de coluna.

  <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-2b66775776f2fada22de18f380fa266a8d1cacfe%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

## Noções básicas de Markdown

Toda a sintaxe Markdown é válida no PocketBlocks.

* **Títulos**: Use hashtag (#) antes do título. Mais hashtags, nível de título mais baixo.
* **Parágrafos**: use uma linha em branco para separar os textos em parágrafos.
* **Quebras de linha**: adicione pelo menos dois espaços em branco no final de uma linha e pressione **Enter** para iniciar uma nova linha.
* **Ênfase**: Use um asterisco único (∗) antes e depois do texto para convertê-lo em texto *itálico*, asteriscos duplos (∗∗) para texto em **negrito** e asteriscos triplos (∗∗∗) para *\*\* itálico negrito \*\** texto.
* **Blockquotes**: Use o colchete angular de fechamento (>) para criar uma blockquote.
* **Listas**: use hífen (-), asterisco (∗) ou sinal de mais (+) seguido de um espaço em branco para criar uma lista não ordenada e use números seguidos de um ponto final (.) para criar uma lista ordenada.
* **Código**: Use crases (\`) antes e depois do código para denotar `` `code` `` em texto simples, e três crases (\`\`\`) para apresentar ` ```bloco de código ` \`\` \`.
* **Réguas horizontais**: Use pelo menos três asteriscos (∗∗∗), hífens (---) ou sublinhados (\_ \_ \_) no início de uma linha para criar uma régua horizontal.
* **Links**: Use colchetes (\[]) para o texto de exibição e parênteses (()) para o endereço do link. Observe que não deve haver espaço entre eles. Por exemplo, `[PocketBlocks](https://github.com/pedrozadotdev/pocketblocks)`.
* **Imagens**: Use um ponto de exclamação (!) para iniciar uma inserção de imagem e, em seguida, use colchetes (\[]) para o texto alternativo e parênteses (()) para o endereço do link ou caminho de origem. A legenda pode seguir os parênteses ou começar em uma nova linha.
* **Caracteres de escape**: Use barra invertida (\\) para exibir os símbolos especiais que o Markdown usa. Por exemplo, para imprimir ` `` ` em texto simples, você deve usar `` \`\` `` em Markdown.

Para obter mais informações, consulte [Guia de Markdown](https://www.markdownguide.org/basic-syntax/).

## Extensão GFM

Você também pode usar extensões GitHub Flavored Markdown (GFM) para sintaxe adicional.

* **Notas de rodapé**: use o acento circunflexo (^) e o número entre colchetes (\[]) para inserir notas de rodapé. Para obter mais informações, consulte [Notas de rodapé](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#footnotes).
* **Linhas tachadas**: Use til duplo (\~\~) antes e depois do texto para adicionar linhas tachadas. Para obter mais informações, consulte [Estilização de texto](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#styling-text).
* **Tabelas**: use hífens (-) separados pela barra vertical (|) para criar a linha de cabeçalho de uma tabela e continue usando a barra vertical para separar o conteúdo nas células. Para obter mais informações, consulte [Tabelas (extensão)](https://github.github.com/gfm/#tables-extension-).
* **Listas de tarefas**: use um espaço em branco entre colchetes (\[ ]) no formato de lista para criar listas de tarefas. Para marcar uma tarefa concluída, substitua o espaço em branco pela letra *x*. Para obter mais informações, consulte [Listas de tarefas](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#task-lists).

## Suporte HTML

No PocketBlocks, você pode usar a maioria das tags e propriedades HTML. Para obter mais informações, consulte [Incorporar HTML no Markdown](https://www.markdownguide.org/basic-syntax/#html).

{% hint style="warning" %}
Por motivos de segurança, algumas tags HTML, incluindo **iframe** e **script**, não são permitidas no PocketBlocks.
{% endhint %}

### Apêndice: Tags HTML suportadas

```html
<h1>
<h2>
<h3>
<h4>
<h5>
<h6>
<br>
<b>
<i>
<strong>
<em>
<a>
<pre>
<code>
<img>
<tt>
<div>
<ins>
<del>
<sup>
<sub>
<p>
<ol>
<ul>
<table>
<thead>
<tbody>
<tfoot>
<blockquote>
<dl>
<dt>
<dd>
<kbd>
<q>
<samp>
<var>
<hr>
<ruby>
<rt>
<rp>
<li>
<tr>
<td>
<th>
<s>
<strike>
<summary>
<details>
<caption>
<figure>
<figcaption>
<abbr>
<bdo>
<cite>
<dfn>
<mark>
<small>
<span>
<time>
<wbr>
<input>
```


# Módulo

Ao criar um aplicativo, você deseja reutilizar componentes e consultas em diferentes aplicativos. Módulos são o que você precisa. Um módulo compreende componentes e consultas. Você pode inserir um módulo em um aplicativo ou em outros módulos (referidos como *aplicativos externos* no restante deste documento) e ele funciona como um único componente.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-890de16454f06e2c138f2b045955907d67139857%2F01.png?alt=media" alt=""><figcaption><p>Construindo um<a href="#demo-a-statistics-module">módulo estático</a></p></figcaption></figure>

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-05e9f72fdf4d1f73fd84be95e23000fe44ec2251%2F02.png?alt=media" alt=""><figcaption><p>Reutilize este módulo em qualquer lugar</p></figcaption></figure>

## Noções básicas do módulo

### Criando um novo módulo

Selecione **Novo > Módulo** no canto superior direito da página inicial para entrar no editor do módulo.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-854860101985df5ebcafcdbbc0a038c4ea465ab1%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### Definindo configurações do módulo

Você pode definir as configurações de um módulo na guia **Configurações** do navegador de dados:

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-720dc2fca115fed1e70cb86f5d345710e32a9945%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

* **Entrada**: parâmetros passados ​​para o módulo atual a partir de aplicativos externos.

  <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-60bdafd19000a49c5b5c9c3ab3f1bbcf15a1fff2%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>
* **Saída**: dados expostos a aplicativos externos.

  <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-4b45079f233bd3134e6fbd92879e33a8df52e77a%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>
* **Método**: métodos expostos a aplicativos externos. Por exemplo, você pode definir um módulo com um método `redefinicaoDeTitulo`, para que aplicativos externos possam chamá-lo para redefinir o título do módulo.

  <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-571ba46a9f6499a2328dd4b886f2123685e61414%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>
* **Evento**: os eventos do módulo podem ser tratados por aplicativos externos. Por exemplo, você pode definir um evento chamado `AlteracaoDeDado`, para que aplicativos externos possam adicionar manipuladores de eventos a ele assim que o evento `AlteracaoDeDado` for disparado pelo módulo.

  <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-6fa489082bce78b85ffe5978edc74e31a024b03a%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>

Para mais detalhes, consulte o capítulo [Configurações do módulo](#module-settings).

### UI do módulo de design

As outras áreas do editor de módulos são semelhantes às do editor de aplicativos web. Insira componentes e crie consultas da mesma forma que o processo de criação de aplicativos. No editor de módulo, você pode redimensionar um módulo arrastando o canto inferior direito para o tamanho padrão desejável. Alterne o botão no painel **Propriedades** para controlar se a **altura do componente é dimensionada com o contêiner**. \*\*\*\* Isso funciona apenas para componentes de altura fixa dentro do módulo.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-38b1a21d2922722098c8585bc52fd03ba2a86ca6%2F09.gif?alt=media" alt=""><figcaption></figcaption></figure>

### Inserir módulo em aplicativos ou outros módulos

Ao editar um aplicativo ou módulo, selecione **Inserir > Extensões > Módulos** para exibir os módulos aos quais você tem acesso.

<img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-0c9d4991661376842fbd72e0a607c56b29c156f0%2F10.png?alt=media" alt="" data-size="original">

Em seguida, arraste e solte o módulo na tela, defina os parâmetros de entrada e altere os estilos dentro do painel **Propriedades** do módulo.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-b75855407c7d55ef196af62656c647ed2cc02ea4%2F11.png?alt=media" alt=""><figcaption></figcaption></figure>

Inspecione os dados expostos pelo módulo no navegador de dados.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-c738411e9a46167837d7b017305d1b80ed20ef61%2F12.png?alt=media" alt=""><figcaption></figcaption></figure>

## Configurações do módulo

### Entrada

As entradas do módulo são parâmetros passados ​​ao módulo por aplicativos externos. Os tipos de entrada suportados são **dado**, **texto**, **número**, **lista**, **booleano**, \*\*\*\* e **consulta**. Os primeiros cinco são tipos de dados. Escolha **dados** para não restringi-lo a um tipo de dados específico. Ao escolher o tipo de **consulta**, você pode passar uma consulta de aplicativos externos e acioná-la dentro do módulo. Em seguida, você pode referenciar um parâmetro de entrada do módulo por seu \*\*nome\*\*.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-2bf87506566a10d786cfe3e939aaa14a3ead2d8d%2F13.png?alt=media" alt=""><figcaption></figcaption></figure>

### Demonstração: Um módulo de estatísticas

Esta seção orienta você pelas etapas para criar um módulo de estatísticas e reutilizá-lo em um aplicativo. & #x20;

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-05e9f72fdf4d1f73fd84be95e23000fe44ec2251%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

1. Criando entradas de módulo:

Na guia **Configurações**, clique em **+** **Adicionar** para criar uma nova entrada de módulo e, em seguida, defina seu **nome**, **tipo**, **valor padrão** (opcional) e **dica** (opcional). Neste exemplo, três entradas de módulo são adicionadas: duas entradas de texto `título`, `imagemUrl` e uma entrada numérica `contador`:

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-e5a5441d675834f03a5cc30d009483a575cd96c5%2F14.png?alt=media" alt=""><figcaption></figcaption></figure>

2. Projetando a UI do módulo:
3. Insira um **contêiner** no módulo.
4. Adicione dois componentes **text** e um componente **image** ao contêiner.
5. Ajuste suas propriedades, como layout, altura e estilo.
6. Vincule o valor dos componentes às entradas do módulo. Por exemplo, a **Fonte da imagem** está vinculada ao parâmetro de entrada `imagemUrl.value`.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-c18498c90a9b8df09af57ac886396a1519704991%2F15.png?alt=media" alt=""><figcaption></figcaption></figure>

1. Insira o módulo recém-criado em um aplicativo ou módulo externo e você poderá passar valores para configurar suas propriedades.

   <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-a08665420a439d40ebb22958fd727930372822bb%2F16.png?alt=media" alt=""><figcaption></figcaption></figure>
2. Reutilize o módulo várias vezes, passando diferentes valores de entrada.

   <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-05e9f72fdf4d1f73fd84be95e23000fe44ec2251%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Teste de entrada

Para testar rapidamente a eficácia dos parâmetros de entrada durante a edição de um módulo, você pode usar a função **Teste de entrada**. No **editor de módulo**, selecione o módulo inteiro para realizar testes com dados de entrada simulados no painel **Propriedades**. No exemplo mencionado anteriormente, você pode definir os valores de teste para as três entradas do módulo: `titulo`, `imagemUrl` e `contador`, conforme mostrado abaixo:

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-1b7d26b75ae123b625817bc735a1db311e2f2829%2F17.png?alt=media" alt=""><figcaption></figcaption></figure>

### Saída

As saídas do módulo são os dados expostos a um aplicativo ou outros módulos. Você pode inspecionar as saídas de um módulo no navegador de dados e acessá-las via código JavaScript em `{{ }}`. O exemplo a seguir mostra as saídas em um módulo de filtragem de usuário.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-801f75a7e7d3bdd11e54e185730fe365c465a475%2F18.png?alt=media" alt=""><figcaption></figcaption></figure>

Em seguida, você pode verificar e referenciar as saídas de um módulo em aplicativos ou outros módulos que o utilizam.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-d915b36a825a76968a470b9d5af3a61af77db8e3%2F19.png?alt=media" alt=""><figcaption></figcaption></figure>

### Método

#### Adicionando um novo método

Na guia **Configurações**, clique em **+** **Adicionar** para criar um novo método de módulo. Clique no método para renomeá-lo e selecione uma ação. No exemplo a seguir, o método `limparTudo` foi projetado para limpar o conteúdo em ambas as caixas de entrada. Para conseguir isso, selecione **Executar JavaScript** como a ação e escreva o código JS para chamar o método `limparValor` de ambos os dois componentes de entrada.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-01feb567b75d05fbed971b8923f4d9962cebe48c%2F20.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Ao criar um método para um módulo, você não pode criar parâmetros de entrada para o método e só pode fazer referência a parâmetros dentro do escopo do módulo atual.
{% endhint %}

#### Chamando um método

Ao usar módulos, você pode chamar um método de módulo de duas maneiras:

* Em manipuladores de eventos, selecione **Ação** > **Componente de controle** e, em seguida, selecione **componente** e **método**.

  <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-2103744eff0855a0fa54e9cd6517d5638b651346%2F21.png?alt=media" alt=""><figcaption></figcaption></figure>
* Use notação de ponto em consultas JavaScript. Por exemplo, `modulo1.limparTudo()` chama o método `limparTudo()` de `modulo1`.

#### Testando o Método

Você pode simular a chamada do método de teste na função **Teste de Método**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-3a0c2503d669857b79cd8bfd12ab2174fc2dccc8%2F22.gif?alt=media" alt=""><figcaption></figcaption></figure>

### Evento

Os eventos são usados ​​para transferir sinais de um módulo para aplicativos externos, como definir eventos `pedidoFeito` `pedidoModificado` para um módulo de gerenciamento de pedidos. Você pode adicionar e disparar eventos dentro de um módulo e lidar com eles usando [manipuladores de eventos](/portugues-brasil/construcao-de-aplicativos/event-handlers) externamente.

#### Adicionar um novo evento

Na guia **Configurações**, clique em **+** **Adicionar** para criar um novo evento de módulo. Clique no evento para definir seu nome.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-dc001d9c55e738c7650a6922f47f4c31cc848c35%2F23.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Acionando um evento

No exemplo a seguir, o evento `conteudoAlterado` é acionado quando o conteúdo de qualquer caixa de entrada é alterado. Você pode acioná-lo de duas maneiras:

* Em **Manipuladores de eventos** de ambos os componentes de entrada, clique em **+ Adicionar**, selecione **Alterar** como o evento do componente e **Disparador de evento de módulo** como a ação e, finalmente, selecione o evento do módulo `conteudoAlterado`.

  <figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-d5c0a117f1c98da8e0ae61bd74299a6fe9f1b1c2%2F24.png?alt=media" alt=""><figcaption></figcaption></figure>
* Use notação de ponto em consultas JavaScript: `conteudoAlterado.trigger()`.

#### Manipuladores de eventos

Quando um aplicativo usa um módulo, você pode configurar como o aplicativo atual reage aos eventos do módulo. Por exemplo, em **Manipuladores de eventos** de `modulo1`, clique em **+ Adicionar** e selecione o evento do módulo `conteudoAlterado` e a ação **Mostrar aviso**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-ed24c98c01f4eee9e2d74c1a43cc834eb9f820be%2F25.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Testando Evento

O exemplo a seguir conduz testes de eventos na seção **Teste de Eventos**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-e88c7ff0eeaef8e132b8bff92346e458e3add66a%2F26.gif?alt=media" alt=""><figcaption></figcaption></figure>

## Permissions

Os usuários finais não recebem permissões automaticamente para visualizar módulos em aplicativos ou outros módulos com os quais tenham permissão de visualização. Por isso, você deve conceder permissão nos módulos como faz com os aplicativos. Para obter mais informações, consulte [permissões para recursos](/portugues-brasil/gerenciamento-do-espaco-de-trabalho/permissions-for-resources).

## Lançamentos e versões

PocketBlocks armazena as versões históricas de seus módulos para suas referências. Clique em **Visualizar > Publicar** no canto superior direito. O gerenciamento de lançamento de um módulo é idêntico ao de um aplicativo. Para obter informações detalhadas, consulte [gerenciamento de versões](/portugues-brasil/construcao-de-aplicativos/version-and-release-management#release-management).

{% hint style="info" %}
Para um módulo não publicado, os aplicativos e módulos usam sua versão mais recente; enquanto para um publicado, você precisa publicá-lo novamente para sincronizar suas alterações mais recentes.
{% endhint %}


# Interface de usuário do aplicativo


# Estilo, tema e usabilidade

Uma boa interface de usuário (UI) melhora a experiência do usuário (UX) e aumenta o envolvimento do usuário. Você pode personalizar o estilo de cada componente no PocketBlocks e usar o recurso de tema para projetar a interface por aplicativo ou espaço de trabalho. Recursos como configuração de ícones e mensagens de dicas tornam a interação do aplicativo mais fácil de usar.

## Estilos de componentes

Você pode modificar o estilo de todos os componentes na guia **Propriedades**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-095f63646d2118a8934010d418827e4d471156f3%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Clique no seletor de cores para selecionar uma cor ou escreva o código de cores CSS na caixa de texto.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-133ea217cef313f7f6d24934730112a8f5ec28bd%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

Você também pode escrever JavaScript na caixa de texto para controlar condicionalmente a configuração de estilo do componente.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-1ec9733fb8a81b9d26fa3f025d8de7acc6bfb4df%2F03.gif?alt=media" alt=""><figcaption></figcaption></figure>

## Temas

O recurso de tema ajuda você a definir rapidamente os estilos de todos os seus aplicativos em um espaço de trabalho, como a cor primária dos aplicativos e a cor de fundo padrão dos contêineres.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-fdbf2b797c2a87b84e21874bb49cf9538c471142%2F04.gif?alt=media" alt=""><figcaption></figcaption></figure>

### Criando um tema

Os administradores do workspace têm acesso às configurações do tema. Na página inicial do PocketBlocks, vá para **Configurações** > **Temas** e clique em **+ Criar tema**. Insira o nome do tema e selecione um dos temas padrão predefinidos como ponto de partida.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-fbaba1b6547c6be681b428073443688804009749%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

Visualize o efeito do tema em tempo real à direita.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-5c584f13a0ce9e7982f3dc20b67f95f28318b919%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

### Aplicando um tema

No editor do aplicativo, mude o tema clicando em ⚙️ na barra lateral esquerda. Selecione um tema em **Configuração de tema**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-d58ad1700cfb9d526b5b16305498cb1a714b8924%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>

Você também pode definir o tema padrão para todos os seus aplicativos em um espaço de trabalho em **Configurações** > **Temas** na página inicial do PocketBlocks.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-4f02c0cb4285aea794e6b3abf6eb0d9c87fd45f7%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>

### Alternando temas dinamicamente

Você pode acessar a variável global `theme` e chamar o método `theme.switchTo()` para permitir que os usuários finais mudem o tema dos aplicativos de seu lado usando JavaScript. A variável global `theme` possui três campos. Você pode visualizá-los no navegador de dados.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-6994426cab6c2d05b795c926cd65bdf1cf0addd7%2F09.png?alt=media" alt=""><figcaption></figcaption></figure>

* `id` e `name` são strings, indicando o ID e o nome do tema atual. Quando seus valores estão vazios, o tema padrão é aplicado.
* `allThemes` é um array, incluindo todas as informações dos temas disponíveis no espaço de trabalho atual.

O método `theme.switchTo()` alterna o tema no lado do usuário final e requer apenas um ID do tema. Quando o valor passado é uma string vazia `""`, o tema padrão é aplicado. Assim que o usuário final mudar de tema, ele será salvo no armazenamento local do navegador do usuário. E esse tema substituirá o tema padrão e se aplicará a todos os aplicativos usados ​​no mesmo navegador.

#### Demonstração

Combinando listas de opções e eventos, os usuários finais podem mudar o tema dentro do aplicativo.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-b4c4757e07444b87845ab0722869c81a3f0cf3e8%2F10.gif?alt=media" alt=""><figcaption></figcaption></figure>

Siga as etapas abaixo para incluir esta função em seu aplicativo.

1. Arraste e solte um componente **Seletor** na tela. Defina o valor dos dados da seguinte maneira.

<pre class="language-Plain"><code class="lang-Plain"><strong>{{[{ id: "", nome: "Padrão" }, ...theme.allThemes]}}
</strong></code></pre>

2. Defina os rótulos e valores como `{{item.nome}}` e `{{item.id}}` respectivamente. Em seguida, você poderá visualizar o tema padrão e todos os outros temas disponíveis na área de trabalho atual.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-83842f369b714bbd9bb55db0233ee25a643739a9%2F11.png?alt=media" alt=""><figcaption></figcaption></figure>

3. Insira um componente **Botão** em sua tela para mudar de tema. Adicione um evento ao botão, selecione "Executar JavaScript" como a ação e execute o método `theme.switchTo()` que assume o valor do componente **Seletor**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-3fe7632126564a4410cc0689f0ea0a7ffe21b69b%2F12.png?alt=media" alt=""><figcaption></figcaption></figure>

## CSS customizado

PocketBlocks fornece um recurso CSS personalizado para um estilo de UI mais flexível e personalizado.

### CSS no nível do aplicativo

No editor de aplicativos, clique em ⚙️ na barra lateral esquerda, selecione **Scripts e estilo** > **CSS** e escreva o código CSS para o aplicativo atual.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-dc72a3a4d3f0dda0d99980bffd19f4af4c904ef6%2F13.png?alt=media" alt=""><figcaption></figcaption></figure>

Por exemplo, insira o componente de texto `texto1`. Em seguida, use `.texto1` como nome do elemento e modifique seu estilo CSS.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-0ee7475ba2361e1ad91f1788d5c20a126134d79e%2F14.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
É recomendado modificar os estilos dos componentes em **Propriedades** > **Estilo** porque o DOM de um estilo CSS ajustado pode mudar conforme o sistema itera.
{% endhint %}

### Pré-carregando CSS

No PocketBlocks, os administradores do espaço de trabalho também podem definir estilos CSS pré-carregados para todos os aplicativos no espaço de trabalho. Abra **Configurações** e clique em **Avançado** > **Pré-carregar CSS**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-fd0ffc6c9e699076d6f3eeb5270c90a923407164%2F15.png?alt=media" alt=""><figcaption></figcaption></figure>

É altamente recomendado usar seletores CSS da seguinte forma:

| Nome da classe     | Descrição                    |
| ------------------ | ---------------------------- |
| cabeçalho superior | Barra de navegação superior  |
| contêiner raiz     | Contêiner raiz do aplicativo |

O nome de cada componente funciona como o nome da classe. Por exemplo, para o componente `texto1`, você pode usar `.texto1` como nome de classe e escrever código CSS para ele. E os nomes das classes compartilham o mesmo formato: `ui-comp-{TIPO_DO_COMPONENTE}` — por exemplo, você pode usar `.ui-comp-select` para definir o estilo CSS de todos os componentes seletores. Todos os nomes de classes dos componentes estão listados a seguir.

```Plain
input
textArea
password
richTextEditor
numberInput
slider
rangeSlider
rating
switch
select
multiSelect
cascader
checkbox
radio
segmentedControl
file
date
dateRange
time
timeRange
button
link
dropdown
toggleButton
text
table
image
progress
progressCircle
fileViewer
divider
qrCode
form
jsonSchemaForm
container
tabbedContainer
modal
listView
navigation
iframe
custom
module
jsonExplorer
jsonEditor
tree
treeSelect
audio
video
drawer
carousel
collapsibleContainer
chart
imageEditor
scanner
```

Evite usar nomes de classes que possam mudar com iterações, como `sc-dkiQaF bfTYCO`.PocketBlocks suporta [pré-processador CSS](https://stylis.js.org/), você pode usar o aninhamento CSS para melhorar a eficiência, por exemplo:

```css
.texto1 {
  span {
    color: red;
    font-weight: bold;
  }
}
```

Todo o CSS personalizado para aplicativos é salvo no espaço chamado `#app-{ID_DO_APP}`, e o CSS dos módulos é salvo no espaço chamado `#module-{ID_DO_MODULO}`.Se o seu CSS pré-carregado não funcionar corretamente, pode ser substituído pelo tema ou estilos de componente com maior prioridade. Abra o navegador **Inspecionar** para verificar.

### Demo 1: Quebra de linha no cabeçalho da tabela

Para permitir quebra de linha no cabeçalho da tabela, insira o seguinte código em **Script e estilo** > **CSS**.

```css
.tabela1 {
  th div {
    white-space: pre-wrap;
    word-break: break-word;
    max-height: unset;
  }
}
```

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-cb7fbaacb550e409b629c75c321b118c76296f57%2F16.png?alt=media" alt=""><figcaption></figcaption></figure>

### Demo 2: Família de fontes personalizadas

Para usar uma família de fontes personalizada, você precisa primeiro defini-la e depois aplicá-la. Insira o seguinte código em **Script e estilo** > **CSS** para aplicar a fonte "Fredoka One" a todos os componentes de texto usando o modo Markdown no aplicativo.

```css
@font-face {
  font-family: "Fredoka One";
  font-style: normal;
  font-weight: 400;
  src: url(https://fonts.gstatic.com/s/fredokaone/v13/k3kUo8kEI-tA1RRcTZGmTlHGCaen8wf-.woff2)
    format("woff2");
}

.ui-comp-text .markdown-body {
  font-family: "Fredoka One";
  font-size: 30px;
}
```

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-dd6f08a8a3d19d27d47336bd4804c7bb8d9187d6%2F17.png?alt=media" alt=""><figcaption></figcaption></figure>

## Interação amigável

PocketBlocks sempre faz jus à eficiência, segurança e design fácil de usar.

### Ocultar componentes da UI

Defina as propriedades ocultas dos componentes quando necessário para evitar sobrecarga de informações. Por exemplo, ao criar um formulário de coleta de sugestões, você pode definir a caixa de entrada como visível ou oculta dependendo da seleção do usuário. <img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-57cbd086350ba16e972fbf8731547f395b5ade03%2F18.gif?alt=media" alt="" data-size="original">

Para conseguir este efeito, defina a propriedade oculta do componente `areaDeTexto1` com o código:

```JavaScript
{{Number(radio1.value) === 1 ? 'false' : 'true'}}
```

Quando o valor do componente `radio1` é “1”, o valor da propriedade oculta é “false”; caso contrário, o valor será "verdadeiro". O layout do componente é ajustado automaticamente.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-861b82784ae66bd62c052808e250bfb83796b767%2F19.png?alt=media" alt=""><figcaption></figcaption></figure>

### Configuração de ícones

Os ícones são intuitivos e podem ser alternativas ao texto em alguns casos. O uso adequado dos ícones proporciona aos usuários uma melhor experiência visual e os ajuda a usar o aplicativo com mais facilidade.

Ícones de prefixo e sufixo estão disponíveis para alguns componentes, como **Botão**. Adicione ícones em **Propriedades** > **Layout**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-5b26ea4b391edaf9ca44367f195c76b9e66c349a%2F20.png?alt=media" alt=""><figcaption></figcaption></figure>

Você pode selecionar ícones predefinidos ou escrever código JS para inserir ícones, por exemplo, `{{ "/icon:solid/Users" }}`.

### Espaço reservado e dica de ferramenta

As dicas melhoram a usabilidade do aplicativo – por exemplo, mostrar dicas para a entrada ajuda os usuários a interagir melhor com o aplicativo.

* Espaço reservado: é exibido no campo de entrada vazio para solicitar ao usuário o que digitar.
* Dica: Adiciona um sublinhado ao rótulo. Os usuários podem ver a dica de ferramenta passando o mouse.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-78b458697f1761bf9b77b95ccf921d3c75dce4e2%2F21.png?alt=media" alt=""><figcaption></figcaption></figure>

### Notificações

Notificações são mensagens enviadas diretamente aos seus usuários para lembrá-los do status de suas operações, confirmar o sucesso ou ajudá-los a prosseguir.

#### Notificações globais

Notificações globais para determinadas interações do usuário fornecem feedback oportuno aos usuários. PocketBlocks oferece quatro tipos de notificações globais: **Informações**, **Sucesso**, **Aviso** e **Erro**.

Você pode definir notificações globais de três maneiras:

1. Definindo em **Manipuladores de eventos** > **Ação** > **Mostrar notificação**. Consulte [Mostrar notificação](/portugues-brasil/construcao-de-aplicativos/event-handlers#show-notification) (Manipuladores de eventos).
2. Definindo **consultas JavaScript** com [funções integradas](/portugues-brasil/construcao-de-aplicativos/write-javascript/built-in-javascript-functions).
3. Definindo na aba **Notificação** nas configurações de consulta. Consulte [Guia Notificação](https://github.com/internoapp/pocketblocks/blob/main/docs/pt-br/queries/query-basics.md#notification-tab-and-advanced-tab).

### Efeito de carregamento

Quando uma consulta demora para ser executada, você pode definir o efeito de carregamento para informar aos usuários que a consulta está em execução e evitar que executem operações frequentes.

Por exemplo, o efeito de carregamento do botão Enviar é `{{form1SubmitToHrmsEn1.isFetching}}`. Clicar no botão aciona a execução da consulta `form1SubmitToHrmsEn1` e, durante esse processo, o botão é exibido com o efeito de carregamento.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-0fd77d853092b1307dc855b9c4e2c69f7435d0e4%2F22.gif?alt=media" alt=""><figcaption></figcaption></figure>

#### Modal de confirmação

Você pode definir uma modal de confirmação para uma verificação dupla para seus usuários quando eles realizam operações como adicionar, modificar ou excluir dados. Na guia **Avançado** da consulta, alterne **Mostrar um modal de confirmação antes de executar** e insira uma mensagem de confirmação.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-398d349be17679cde526665e1f0e5b8714ea29a3%2F23.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Design de formulário

Formulários são frequentemente usados ​​para coletar informações. Para obter mais detalhes sobre como criar formulários produtivos e fáceis de seguir, consulte [Criar um formulário eficiente e fácil de usar](/portugues-brasil/construcao-de-aplicativos/design-app-ui/design-an-efficient-and-user-friendly-form).


# Crie um formulário eficiente e fácil de usar

### Selecione os componentes de entrada adequados

O design UX dos componentes de entrada em um formulário é crucial para a eficiência do formulário. Componentes escolhidos corretamente podem economizar esforço dos usuários e levar a melhores resultados. PocketBlocks oferece uma variedade de componentes de entrada, incluindo entrada de texto, entrada de número, lista de opções e botões de opção, cada um dos quais funciona para diferentes cenários.

Por exemplo, quando a entrada é gerada a partir de dados, use a lista de opções para permitir que os usuários preencham a entrada rapidamente.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-00844451b6ada7d2539c99615e23cc37d202dcf5%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Outros componentes de entrada, como rádio, são realmente úteis quando os usuários precisam escolher diretamente entre duas opções, por exemplo, para indicar se gostariam de se inscrever em uma atividade específica, como uma conferência.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-caf1188a9a71ab6af6ddf60fe806bef97ffe36ea%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

A entrada de números também é um tipo de componente comumente usado – por exemplo, em um sistema de gerenciamento de pedidos.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-48f444d611c61dfa62461e1ce07ff5e712f46eab%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### Mantenha o layout limpo e consistente

Mantenha todos os comprimentos dos campos de entrada iguais para tornar o formulário visualmente organizado e coloque todos os campos de entrada em uma única coluna para obter melhor legibilidade.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-9c7555f95cf155b216c28980164c79dbee6b2ced%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

### Agrupe o conteúdo com o divisor PocketBlocks

Use o componente PocketBlocks **Divisor** para agrupar campos de entrada relevantes para ajudar os usuários a processar informações de maneira organizada.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-2111ade1e2b8fb1ccf17f1ff3e6ab44fd66f3d90%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

### Adicionar feedback do usuário

O componente Formulário é frequentemente usado para operações CRUD, que às vezes podem ser arriscadas devido a erros humanos. Para evitar operações CRUD prejudiciais, você pode adicionar um modal de confirmação antes que os usuários enviem o formulário.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-cc581455b4c27367316216f92fa18bd939409dcc%2F06.gif?alt=media" alt=""><figcaption></figcaption></figure>

Da mesma forma, uma notificação após o envio dos usuários fornece feedback oportuno. Você pode adicionar uma notificação global ao botão Enviar. No PocketBlocks, você pode adicionar notificações globais de três maneiras. Veja [notificação global](/portugues-brasil/construcao-de-aplicativos/design-app-ui/style-theme-and-usability#global-notifications) para saber mais.

### Limpe os campos de entrada no envio

Limpar os campos de entrada em um formulário após o envio ajuda os usuários a prosseguir com os envios subsequentes. Você pode definir na guia **Propriedades** e alternar **Redefinir após envio bem-sucedido**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-1c7f180a08c73d224e04050f2d745bcbc7fe3675%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>

No entanto, às vezes é melhor deixar o formulário desmarcado — por exemplo, quando muitos dos valores permanecem os mesmos em envios subsequentes ou quando o usuário edita continuamente os dados. Nesses casos, você pode inserir um botão com um manipulador de eventos para limpar cada entrada ao clicar.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-70e2601335fab83219b4eb9dcfbf774406c04683%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>


# Navigação

**Navegação** agrega seus aplicativos na barra lateral esquerda e orienta você para encontrar rapidamente o aplicativo necessário.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-f10c70bd1b26154ac6524d025d71b885e946809d%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Na página inicial do PocketBlocks, clique em **Novo** e selecione **Navegação** para criar uma página de navegação.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-73b80f4764e27c182e140d49b2f35f66a7150608%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

## Itens do menu

No editor de **Navegação**, clique em **+ Novo** para adicionar itens de menu.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-873566feff0adf4a85517dd86f7d39637efa6f2b%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

Selecione um item de menu, escolha o aplicativo para navegar e altere o rótulo e o ícone, se necessário. O aplicativo é exibido na tela em tempo real.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-459d698c090dc931e1f0d9d97b414ad4f90e4878%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

### Adicionando itens de submenu

Para adicionar itens de submenu, clique em `···` > **Adicionar item de submenu** ou arraste `⋮⋮` para tornar um item de menu subordinado a outro.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-e18eba95f41950f9ea204a329ce1e1d728b25f7c%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-e293c845f90684a086320474674fd429e9f9ba09%2F06.gif?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Um item de menu pai só pode expandir ou dobrar os itens do submenu. Você não pode vincular um aplicativo a ele.

Quando você exclui um item de menu pai, todos os itens de submenu nele são excluídos ao mesmo tempo.
{% endhint %}

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-b8f76f31bb08ac3e7589c5d4463c4b6b8c2cd129%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>

### Adicionando parâmetros de URL

Adicione parâmetros de consulta de URL ou parâmetros de hash a um item de menu com `chave` e `valor`.![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-884d21193c5894881ade8604d4c672d6bd803a1d%2F08.png?alt=media)

Em seguida, clique no item de menu na tela e os parâmetros serão anexados à URL do aplicativo a ser aberto. Você pode verificar na guia **Globais** no painel esquerdo.![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-6538e9a9c4ab4f2c62b40108ed99eedf9687ce0f%2F09.png?alt=media)

{% hint style="info" %}
Para referenciar os parâmetros de URL, use `{{url.query.chave1}}` ou `{{url.hash.chave1}}` em seu aplicativo.
{% endhint %}

Para obter mais informações sobre parâmetros de URL, veja Ir para app.

### Visibilidade dos itens do menu

Por padrão, um item de menu fica oculto para usuários sem permissão do aplicativo. Quando você desativa esta opção, os usuários podem ver o item de menu, mas não podem ver o aplicativo ao qual ele faz referência.![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-d4b44db77c0a6943532e8581d7fce16b9daee772%2F10.png?alt=media)

## Permissões

As permissões para navegações são as mesmas dos módulos e aplicativos. Consulte Permissões para recursos.


# Atalhos de Teclado

## Atalhos de teclado integrados

Os atalhos de teclado são uma ferramenta poderosa que pode melhorar significativamente a produtividade e a eficiência ao trabalhar em um computador. Com a capacidade de atribuir teclas personalizadas a comandos usados ​​com frequência, as tarefas podem ser concluídas rapidamente e com esforço mínimo. Isto é particularmente útil para indivíduos que dependem muito da entrada do teclado, como programadores, escritores ou designers.

Os atalhos de teclado existem há décadas e a maioria dos aplicativos de software vem com um conjunto de atalhos padrão. PocketBlocks oferece atalhos de teclado integrados para ajudá-lo a trabalhar na interface de maneira mais rápida e eficiente, com maior precisão de controle.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-aff01be01dd9b19dcef2a9f126cfad3ccdb94cb0%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

### Globais

Atalhos de teclado globais nas interfaces do PocketBlocks.

| Atalho | Descrição                   |
| ------ | --------------------------- |
| `?`    | Alternar atalhos de teclado |

### Editor de aplicativos

Atalhos de teclado no [editor de aplicativos](#app-editor).

| Atalho        | Descrição                 |
| ------------- | ------------------------- |
| `⌘` + `B`     | Alternar painel esquerdo  |
| `⌘` + `J`     | Alternar painel inferior  |
| `⌘` + `U`     | Alternar painel direito   |
| `⌘` + `.`     | Alternar todos os painéis |
| `⌘` + ⇧ + `P` | Visualização              |
| `⌘` + `Z`     | Desfazer                  |
| `⌘` + ⇧ + `Z` | Refazer                   |
| `⌘`           | Mostrar grade             |

### Componente

Atalhos de teclado para controlar componentes.

| Atalho                | Descrição        |
| --------------------- | ---------------- |
| `⌘` + Clique          | Selecione vários |
| `⌘` + `A`             | Selecionar tudo  |
| `⌘` + `C`             | Copiar           |
| `⌘` + `X`             | Corte            |
| `⌘` + `V`             | Colar            |
| `←` `↑` `→` `↓`       | Mover            |
| `⌘` + `←` `↑` `→` `↓` | Redimensionar    |
| `DEL`/`Backspace`     | Excluir          |
| `ESC`                 | Desmarcar        |

### Editor de consultas

Atalhos de teclado no editor de consultas.

| Atalho    | Descrição                |
| --------- | ------------------------ |
| `⌘` + `↵` | Execute a consulta atual |

### Editor de texto

Atalhos de teclado no editor de texto.

| Atalho       | Descrição                |
| ------------ | ------------------------ |
| `⌘` + `L`    | Formato                  |
| `⌘` + Clique | Abrir no painel esquerdo |

## Custom keyboard shortcuts

## Atalhos de teclado personalizados

Você pode definir atalhos de teclado personalizados no nível do aplicativo. Vá para ⚙️ na barra lateral esquerda > **Configurações do aplicativo** > **Atalhos personalizados**. Clique em **+ Adicionar** para adicionar novos atalhos para ações específicas. Em seguida, você pode clicar em um atalho personalizado para modificá-lo ou clicar nos três pontos `···` para excluí-lo.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-f2906d668e434e4f975cb879c189b31821f10859%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Os atalhos de teclado do PocketBlocks são melhor configurados para evitar conflitos com os atalhos de teclado do navegador, caso não possam ser acionados com sucesso.
{% endhint %}


# Gerenciamento de versão e lançamento

O gerenciamento de versão e lançamento visa fornecer uma versão estável ao vivo para usuários finais e permite que você crie e teste seu aplicativo com segurança.

Por padrão, os usuários finais interagem com a versão mais recente do seu aplicativo. Depois de esboçar e modificar suas ideias, você pode visualizar e comparar com diferentes versões do histórico e, finalmente, publicar a versão que atenda a todas as suas necessidades. A versão recém-publicada agora fica ativa e todas as suas atualizações futuras não afetarão a versão ativa até que você publique novamente.

## Histórico de versões

PocketBlocks armazena automaticamente todas as alterações do seu histórico durante a construção de um aplicativo, como adição ou exclusão de componentes, ajuste de propriedade dos componentes, reorganização do layout e atualização de uma função personalizada. Você pode usá-lo para consultar suas ideias anteriores ou reverter para uma versão anterior.

As versões do histórico do aplicativo só podem ser acessadas por administradores.

### Visualizando uma versão do histórico

Você pode visualizar qualquer versão de seus rascunhos anteriores. Clique em **Visualizar** **>** **Histórico**.

![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-4bba5ec95f77fc18a982b36cde3c96be49f3f954%2F01.png?alt=media)

### Restaurando uma versão do histórico

Você pode restaurar seu rascunho atual para uma versão do histórico.

1. Selecione a versão de destino na lista de versões do histórico
2. Clique em **Restaurar esta versão** na barra superior

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-56ca20f7070e2675a243edd6be1bf5f8032f10a4%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

## Gerenciamento de publicações

Os aplicativos geralmente são atualizados regularmente para incluir novos recursos, melhorar processos de negócios e corrigir falhas. No entanto, o desenvolvimento de uma nova versão de um aplicativo leva tempo e você precisa garantir que a experiência do usuário não seja afetada durante esse progresso.

Por padrão, os usuários finais interagem com a versão mais recente do seu aplicativo. Depois de finalizar o esboço de uma versão mais recente do seu aplicativo, você poderá publicá-lo. Clique em **Visualizar > Publicar**.

![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-3208c41bf68d324b05503052ef5e1567a81cec91%2F03.png?alt=media)

Agora a versão recém-lançada está disponível para todos os usuários finais e todas as suas atualizações futuras não afetarão a versão ativa até que você publique novamente.


# Desenvolva plug-ins de componentes de UI

Com os plug-ins do PocketBLocks, você pode desenvolver componentes personalizados que sejam consistentes com os componentes nativos para seus cenários específicos.

## Initialização

Execute os comandos a seguir:

```bash
# Iniciação do projeto
yarn create pocketblocks-plugin meu-plugin

# Vá para a raiz do projeto
cd meu-plugin

# Inicie o ambiente de desenvolvimento
yarn start
```

## Ambiente de desenvolvimento de componentes

Após executar `yarn start`, o navegador é aberto automaticamente e você entra no ambiente de desenvolvimento do componente.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-2ea7498f47d82d0af5acb15312197588e7ff4dbd%2F01.jpeg?alt=media" alt="Captura de tela do ambiente de desenvolvimento de componentes"><figcaption></figcaption></figure>

## Configurando o plug-in

No campo `openblocks` no arquivo `package.json`, você precisa definir as propriedades do componente. Por exemplo, a seguir está a explicação de vários campos:

* `comps` define os componentes da UI contidos no plugin. Para cada componente, o nome da chave do objeto é a identidade exclusiva e o valor são os metadados.
* `comps[algumaChaveDeComponente].name` define o nome do componente mostrado na aba **Inserir**.
* `comps[algumaChaveDeComponente].icon` define o ícone do componente mostrado na tela. Use um caminho relativo para onde o arquivo `package.json` está localizado.
* `comps[algumaChaveDeComponente].layoutInfo` define o layout do componente:
  * w: largura do componente. Contado pelo número de células da grade (intervalo: 1 - 24).
  * h: altura do componente. Contado pelo número de células da grade (intervalo: >= 1).

```bash
  "openblocks": {
    "description": "",
    "comps": {
      "ola_mundo": {
        "name": "Olá mundo",
        "icon": "./icons/ola_mundo.png",
        "layoutInfo": {
          "w": 12,
          "h": 5
        }
      },
      "contador": {
        "name": "Contador",
        "icon": "./icons/ola_mundo.png"
      }
    }
  }
```

## Exportando componentes

Para exportar todos os componentes, use `src/index.ts`, por exemplo:

```bash
import OlaMundoComp from "./OlaMundoComp";

export default {
  ola_mundo: OlaMundoComp,
};
```

O objeto exportado padrão `chave` precisa ser consistente com a `chave` configurada em `comps` no arquivo `package.json`.

## Publicando plug-ins

Ao terminar de desenvolver e testar o plugin, você poderá publicá-lo no registro npm. Faça login no registro npm localmente e execute o seguinte comando:

```
yarn build --publish
```

Se você não especificar o parâmetro `--publish`, o arquivo `tar` será salvo na pasta raiz.

## Importando plug-ins

No aplicativo PocketBLocks, clique em **Inserir** > **Extensões** > **Adicionar plug-in npm** no painel direito. <img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-61d836518578324db0c3851ffd1eb66a5d6bce90%2F02.png?alt=media" alt="" data-size="original">

Insira o URL ou nome do seu pacote npm e então você poderá usar seus componentes personalizados.

```bash
meu-plugin

# or

https://www.npmjs.com/package/meu-plugin
```

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-bbad4d457ac4be913d733ae7920f82ef9458eeb4%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

## Demonstração de código

Para demonstração de código, consulte o [Github](https://github.com/pedrozadotdev/pocketblocks/tree/main/client/packages/openblocks-plugin-demo) do PocketBlocks.


# Autenticação

PocketBlocks oferece uma lista enorme de opções de autenticação. Se você pode usá-lo no [Pocketbase](https://pocketbase.io/), você pode usá-lo no PocketBlocks.

## Habilitando opções de autenticação

Por padrão, a autenticação com nome de usuário e e-mail está habilitada.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-9e4d38488bc50ad64758217c9d67005645d9aecb%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>

Para permitir que os usuários se autentiquem com **provedores OAuth**, acesse o painel de administração do Pocketbase, **Settings** no menu lateral, selecione **Auth providers** e configure algumas das opções disponíveis.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-6da00dab025bc7869367597b6c4bc4933c29e85a%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

## Cadastro

Por padrão, qualquer pessoa pode se cadastrar. Para desabilitar a página de cadastro (e recurso), crie uma regra com restrições.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-2b92d8eac3ceb7019460b61a2309d689b95392cf%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

## Customização

Você pode personalizar alguns aspectos da página de autenticação. Vá para a página **Configurações do PocketBlocks** e vá para **Autenticação**:

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-e8e94a70d408ee664fbd3caef1196f6c5cd2a4bb%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

Você pode alterar o rótulo de entrada do nome de usuário e aplicar uma máscara selecionando a opção de tipo de login **Local**:

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-6d1bdc1416a20648eb2e129c55298cd63e6ed340%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

Você também pode alterar o nome de um provedor OAuth e seu ícone selecionando a respectiva opção de tipo de login:

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-bbeb42f8dd816aa9028a05adeb8698e55d1b2031%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

## Funcionalidades de email

Para ativar a recuperação de senha e verificação/alteração de e-mail, você precisa configurar um **Servidor SMTP** no Painel de Administração do PocketBase:

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-74a672cf5c5a92a2653fc3176b31e0f6c822621b%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>


# Membros e grupos

No PocketBlocks, você pode organizar os membros do seu espaço de trabalho usando diferentes grupos e atribuir funções aos grupos para gerenciar [permissões para recursos](/portugues-brasil/gerenciamento-do-espaco-de-trabalho/permissions-for-resources). Você pode encontrar configurações de membros e grupos em **users** e **groups** no painel de administração do Pocketbase.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-91b1208a103d401a25199c49541efef6db43c1e6%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

## Gerenciando membros do espaço de trabalho

### Funções e permissões do espaço de trabalho

Os usuários podem ser **Administradores** ou **Membros**. Para ser um **Administradores** o usuário precisa ser um **Pocketbase Admin**, caso contrário, será um **membro**.

| Função        | Permissões em nível de espaço de trabalho e grupo                                                                                                                                                                                                                                                           |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Administrador | <p>Espaço de trabalho</p><ul><li>Modificar informações do espaço de trabalho (nome, logotipo etc.)</li><li>Gerenciar membros do espaço de trabalho</li><li>Ver membros do espaço de trabalho</li></ul><p>Grupos</p><ul><li>Criar grupos</li><li>Excluir grupos</li><li>Gerenciar membros do grupo</li></ul> |
| Membro        | Nenhuma                                                                                                                                                                                                                                                                                                     |

## Gerenciando grupos

O gerenciamento baseado em grupo ajuda a organizar membros de diferentes departamentos funcionais em seu espaço de trabalho. Você pode criar grupos na coleção **groups** do Pocketbase.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-5276e9a2c308b8d697501f78e232b252d43a8a29%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

### Funções e permissões de grupo

As permissões estão listadas na tabela abaixo.

| Função        | Permissões                                                                                                                                                                                             |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Administrador | <ul><li>Alterar nome do grupo</li><li>Excluir grupos</li><li>Gerenciar membros do grupo</li><li>Ver membros do grupo</li><li>Gerenciar aplicativos de grupo</li><li>Ver aplicativos de grupo</li></ul> |
| Membro        | Ver aplicativos do grupo                                                                                                                                                                               |


# Permissões para recursos

Gerencie permissões para aplicativos, módulos, navegações e pastas em seu espaço de trabalho.

As permissões determinam as ações que os usuários podem realizar nos recursos, incluindo aplicativos, módulos, navegações, pastas.

Somente administradores do workspace têm permissão para criar recursos.

## Aplicativos, módulos, **navegações**

As permissões para esses três recursos são as mesmas.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-96ba885ae39e93798709bca30cd6c7fb4d926a03%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

### Compartilhe e defina funções

**Administradores** podem adicionar membros e atribuir uma **função de visualizador** a eles. Ao editar um aplicativo web, um módulo ou uma navegação, clique em **Compartilhar** no canto superior direito e, em seguida, clique em **Adicionar membros**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-79fe2a74a2599dc6424121ad4c3d71f1d50753ed%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

Escolha membros e grupos da lista.

![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-ccb9d853104f255bb5caa950b1ce99b0ccb0653e%2F03.png?alt=media)

### Tornar público

Se quiser tornar um aplicativo, módulo ou navegação pública para todos os usuários (incluindo usuários anônimos), você pode ativar **Tornar o aplicativo público** nas configurações de **Compartilhar**.

![](https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-b53d50a2b57d79e309e09c9f47a29ad191f46323%2F04.png?alt=media)

## Pasta

As pastas ajudam você a organizar os aplicativos, módulos e navegações no espaço de trabalho. Somente **administradores** do espaço de trabalho têm as seguintes permissões para pastas:

* Criar
* Renomear
* Excluir
* Mover os aplicativos, módulos e navegações para dentro ou fora das pastas


# Personalização de marca

PocketBlocks fornece um recurso de white-labeling que permite personalizar a **marca** do seu espaço de trabalho, incluindo logotipo, favicon, nome da marca e cor. Você pode configurar facilmente a marca para combinar com a marca da sua empresa e se beneficiar de experiências consistentes com as ferramentas internas existentes da sua empresa.

## Configurações de marca

Somente **Administradores** têm permissão para personalizar a marca. Navegue até **Configurações do PocketBlocks** e vá para **Marca**.

<figure><img src="https://3319212993-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fbz5pg8HuItSzRC8Qjkc6%2Fuploads%2Fgit-blob-315d54523380208c20b29c1ec1f5b16dc64495ab%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Conforme você altera os dados, a visualização lateral é atualizada em tempo real.

{% hint style="info" %}
Essa personalização se aplica apenas a não administradores, portanto, os administradores continuam a visualizar a marca padrão (PocketBlocks).
{% endhint %}


# Onde estão as fontes de dados/biblioteca de consultas?

PocketBlocks integra Openblocks e PocketBase, ou pelo menos a parte do cliente. Como este projeto visa criar o máximo de flexibilidade possível entre esses dois softwares, optamos por não portar os recursos **fonte de dados/biblioteca de consulta**, pois temos acesso ao [Pocketbase SDK](https://pocketbase.io/docs/client-side-sdks/) por meio do **window\.pb**. Também podemos usar os [recursos de extensão](https://pocketbase.io/docs/js-overview/) do Pocketbase para integração com fontes de dados usando algo como [n8n](https://n8n.io/) ou [Zarpier](https://zapier.com/).

Também fornecemos uma [instância do QueryClient](https://tanstack.com/query/v5/docs/reference/QueryClient) para fins de armazenamento em cache. Você pode acessá-lo com **window\.qc**. Ele usa sessionStorage com staleTime de 5 minutos.


# Embarcando aplicativos

Também é possível incorporar aplicativos PocketBlocks em qualquer página HTML com scripts simples, usando o [SDK PocketBlocks](https://github.com/pedrozadotdev/pocketblocks/tree/main/client/packages/openblocks-sdk) através de **window.$pbl**. Isso permite que você incorpore aplicativos PocketBlocks mesmo sem conhecimento profundo de React ou Desenvolvimento Web.

## Como fazer

Para isso, todas as instalações do PocketBlocks trazem um arquivo **embedded.html** na pasta **pb\_public** com um exemplo de código.

```html
<!DOCTYPE html>
<html lang="pt-BR">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>PocketBlocks Embarcado</title>
    <script type="module" crossorigin src="/js/proxy.js"></script>
    <style>
      .demo-title {
        text-align: center;
      }
      .demo {
        overflow: auto;
        padding: 10px;
      }
      .ops {
        padding: 10px;
      }
      .ops button {
        margin-right: 10px;
      }
    </style>
    <script type="module" crossorigin src="/js/embedded.js"></script>
    <link rel="modulepreload" crossorigin href="/js/<HASH>.js" />
    <link rel="stylesheet" href="/assets/index-<HASH>.css" />
  </head>
  <body>
    <h1 class="demo-title">PocketBlocks Embarcado</h1>
    <div id="app" class="demo"></div>

    <script>
      window.onload = async function () {
        const url = new URL(location.href);
        const appId = url.searchParams.get("appId");
        const baseUrl = url.searchParams.get("baseUrl") || location.origin;
        if (!appId) {
          return;
        }
        const instance = await $pbl.bootstrapAppAt(
          appId,
          document.querySelector("#app"),
          {
            baseUrl,
            moduleInputs: { userName: "Lucy" },
          }
        );

        instance?.on("moduleOutputChange", (output) => {
          console.info("output change:", output);
        });

        instance?.on("moduleEventTriggered", (eventName) => {
          console.info("event triggered:", eventName);
        });

        document.querySelector("#app-ops")?.addEventListener("click", (e) => {
          const target = e.target;
          const key = target.dataset.key;
          if (key === "setModuleInputs") {
            instance?.setModuleInputs({
              userName: "Tom",
            });
          }
          if (key === "invokeMethod") {
            instance?.invokeMethod("setSlider");
          }
        });
      };
    </script>
  </body>
</html>
```

Você pode testá-lo acessando sua instalação local em `http://<host>/embedded.html?appId=<appSlug>`

{% hint style="warning" %}
Apenas **aplicativos** podem ser incorporados em páginas. Não use **navegações** ou **módulos**.
{% endhint %}

{% hint style="info" %}
Não copie o código acima. Sempre acesse seu **embedded.html** para obter o código correto pois o `<HASH>` muda com atualizações.
{% endhint %}


# Overview

## What is PocketBlocks?

**Openblocks + PocketBase = PocketBlocks.**

PocketBlocks is a integration between Openblocks and PocketBase.

Traditionally, building an internal app requires complex frontend and backend interactions with hundreds and thousands lines of code, not to mention work on packaging, integration and deployment. PocketBlocks significantly reduces the work you need to do to build an app.

In PocketBlocks, all you need to do is drag and drop pre-built or self-customized components onto the What-You-See-Is-What-You-Get (WYSIWYG) canvas, PocketBlocks helps you build an app quickly and focus on business logic.

## Why choose PocketBlocks?

* **Open source**: Makes your ideas more feasible.
* **High scalability**: Allows to execute JavaScript almost anywhere you would like to customize your business processes and UI components.
* **Clean design**: Follows the principles of Ant Design and supports display on screens of different sizes. We have a number of UI components, based on which you can freely build dashboard, admin panel, and content management system (CMS).

## How to build an app in PocketBlocks?

Building an internal app basically takes 4 steps:

1. Quickly connect to your Pocketbase API using its SDK.
2. Use pre-built or user-customized UI components to build your app UI.
3. Set up [event handlers](/build-apps/event-handlers) to trigger javascript functions, control components or other actions in reaction to user interactions.
4. Preview and share your app with others.


# Installation

In this article, you will be guided through hosting PocketBlocks on your own server:

### Manual

* Download the binary of your OS and arch from [Release Page](https://github.com/pedrozadotdev/pocketblocks/releases);
* Run `./pocketblocks serve`;
* Access [PocketBlocks App](http://localhost:8090) and create the first admin user.

### Docker

* Get the [docker-compose.yml](https://raw.githubusercontent.com/pedrozadotdev/pocketblocks/main/docker-compose.yml) file;
* Run `docker compose up -d`;
* Access [PocketBlocks App](http://localhost:8080) and create the first admin user.

### Fly.io

* Get the [fly.toml](https://raw.githubusercontent.com/pedrozadotdev/pocketblocks/main/fly.toml) file;
* Edit the `app-name` field;
* Run `flyctl launch`;
* Run `flyctl vol create data`;
* Run `flyctl deploy`;
* Access `https://<your-app-name>.fly.dev` and create the first admin user.

{% hint style="info" %}
Remember that PocketBlocks uses Openblocks as the frontend. The `pb_public` dir is already set up but you can use the `pbl_public` dir and all files from that directory will be served at `<serverAddress>/pbl/` path.
{% endhint %}


# Create a new app

## Create a new web app

Click **New > App** on the upper right of Pocketblocks homepage, and go to the app editor. You can rename the app at the left-top of the editor.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-f20605a3a9488c55c5b4da08648a9e8d1d2d01f7%2F01.gif?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Only workspace **admins** can create apps.
{% endhint %}

## Export and import an app

### Export an app

Click your app name and select **Export to JSON**, the app will be exported to a JSON file.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-b9759dcae355becfd87fddc4d41c0abfcd818c41%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

### Import an app

You can import an existing app in a JSON format by clicking **New > Import**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-0a3a380b4b7687048319896da66b48927f7fa01d%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>


# App editor

A quick look at the app editor before you start

In PocketBlocks, the app editor is where you assemble components, create javascript functions to interact with PocketBase data, and publish your apps. It consists of five areas:

1. Toolbar
2. Canvas
3. Data browser
4. Query editor
5. Component and property pane

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-7e7804c9eb72a1c0cfdfd434e3309081c53d28d5%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

## Toolbar

The Toolbar is made up of a topbar and a left sidebar.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-7e7804c9eb72a1c0cfdfd434e3309081c53d28d5%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

On the topbar, you can configure your app as follows:

* Change the app name
* Export to a JSON file
* Control the visibility of other areas
* Share your app
* Preview and deploy your app
* Check the history versions

On the left sidebar, some options are available as follows:

* Show or hide the **Data browser**
* Set canvas size and app theme
* Manage scripts and CSS style
* Start tutorial for app editor
* Show keyboard shortcuts

## Canvas

The canvas at the center of the editor is where you design and see the overall UI. Drag and drop components onto the canvas, bind them with data and event handlers, and assemble them to build a pleasing and powerful app.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-4df0689fcfa18381dbbeb69a3f06215327305547%2F03.gif?alt=media" alt=""><figcaption></figcaption></figure>

Check out [Design app UI](/build-apps/design-app-ui) for UI layout practices.

## Data browser

The data browser on the left pane contains **Queries**, **Components** and **Globals** sections. Here you can inspect the data in a tree structure. For example, to check the returned data of a specific query or component, find its node in belonging section and click<img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-be6600370e2b0c53146ca7c561cb7770b3d0cae6%2F04.png?alt=media" alt="" data-size="line">to expand.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-100a4fea50166ca60ff2aa14a71268203c8556a0%2F05.gif?alt=media" alt=""><figcaption></figcaption></figure>

## Query editor

The query editor lay at the bottom consists of two sections: query list (with **Queries** and **Metadata** tabs) on the left, and query settings (with **General**, **Notification** and **Advanced** tabs) on the right. Create queries to interact with Pocketbase API here.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-a9d6a0ab1834b35e302c6ad1f5220f3cb2f84cf6%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

You can access the Pocketbase sdk through the **window\.pb** object.

## Component and property pane

The component and property pane is located on the right of the window. Drag components onto the canvas from the **Insert** tab and edit the properties of the components in the **Properties** tab.

![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-1950caf7abe4060c084dafe558fb7223b5e001de%2F07.png?alt=media) ![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-d374ffcb88b8da7e78dedd864e152a2d04216b68%2F08.png?alt=media)

When a component is selected on the canvas, the **Properties** tab will be activated automatically and display properties of that component.


# Event handlers

In PocketBlocks, event handlers are responsible for collecting and processing events from components and queries, and executing subsequent actions. For example, for a **Button** component, you can add an event handler to trigger the **Run query** action in response to the button **Click** event.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-355f17f35287dfb910f307a089f25096d0fb4966%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Set event handlers wisely to provide a reactive and responsive user experience (UX). For example, triggering a **returns all data** query after **insert new data** query finishes enables table automatically refresh.

{% hint style="info" %}
You can add as many event handlers as you want for a single component or query, and these event handlers run concurrently.
{% endhint %}

## Events

### Component events

Different components have different events. For example, **Button** components only have a **Click** event.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-f60f04771e931b181a0daa2b6f342cbf326332f8%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

**Input** components have **Change**, **Focus**, **Blur**, and **Submit** events.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-a98f05bd44cc8d9851a33c5ac3b152a36453bd8a%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### Query events

Running a query can result in success or failure, so queries have two events: **Success** or **Failure**. You can add event handlers to queries in Query editor.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-90417f04a06ffe11d973ff0914f163d97e30f55d%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

## Actions

There are a number of event handler actions available in PocketBlocks for handling different scenarios. Set them in the **Action** dropdown list in an event handler.

![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-63ca9265154af55596c732d0699d0e6dcc4277e4%2F05.png?alt=media)

{% hint style="info" %}
See [advanced](#advanced) on this page to know advanced settings.
{% endhint %}

### Run query

Trigger the selected query.

![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-ee3b546ad05eb64467eb8e6af4a02554090132da%2F06.png?alt=media)

### Control components

To control a component, select a component in the **Component** dropdown list and call one of its methods in the **Method** dropdown list.

![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-17a7ccc19efe32d1b5fc72dcb18ed0cc20cd437e%2F07.png?alt=media)

### Set temporary state

Store data in a [temporary state](/build-apps/write-javascript/temporary-state).

### Go to app

Navigate to an PocketBlocks app with optional query or hash parameters.

| Parameter            | Function                                                                                        |
| -------------------- | ----------------------------------------------------------------------------------------------- |
| <p>URL Query<br></p> | <p>Append <code>?key1=value1\&key2=value2...</code> to the URL of the app to be opened.<br></p> |
| URL Hash             | Append `#key1=value1&key2=value2...` to the URL of the app to be opened.                        |

#### **Use case**

In the **User list** app, click **See info** to navigate to the **User info** app, and the detailed information of the user in the selected row will be displayed.

1. The **User list** app passes `{{currentRow.id}}` in the table row as a URL Query parameter to the **User info** app.

   <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-1b2b8c47f9517c5ee875d0a822a6f5db852c4a41%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>
2. The URL field of the **User info** app global variable will automatically resolve the URL requested by the app. In this case, the value of `url.query` is `{"id":3}`, so the query will retrieve the corresponding user info via `{{url.query.id}}`. See the figure below.

   <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-a266d2ca87d725e21bcd4cfdc8c30e0ea59e4fb1%2F09.png?alt=media" alt=""><figcaption></figcaption></figure>

### Go to URL

Navigate to an external URL.

![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-9ff1a09dcd1e1f951297e5555de3bb360e42dec8%2F10.png?alt=media)

### Show notification

Show a floating notification of informational, success, warning, or error message.

![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-6b25995fa580812164f243f112aba47dfd1e1d40%2F11.png?alt=media)

### Copy to clipboard

Copy a value to the clipboard.

![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-702abbe61107557fc62a6d2ae4bab49a9a0211c7%2F12.png?alt=media)

### Export data

Export data in a certain file type (TXT, JSON, CSV, and Excel).

![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-365ce2d597f8b986b037e15bbdd43433c9764a00%2F13.png?alt=media)

## Advanced

### Only run when

The action can be triggered only under a specified condition. Configure the running condition of an event handler in **Only run when** option, and then the event handler runs only when this condition evaluates to `true`.

### Debounce and throttle

**Debounce** and **Throttle** reduce the frequency of triggering the action.

#### **Debounce**

Debounce delays an action. Once a debounce time is set, the action will not be executed immediately following the event until the debounce time passes. If the event occurs again before the time ends, the debounce time will be retimed. For example, an input component triggers a query once the user changes the text. If the query is expensive to run and you don't want to run it after every single character is typed, you can delay the execution of the query by setting the debounce time. Then the query will only run after the user finishes typing.

#### **Throttle**

Throttle lets an action happen only once during a specified period of time. By default, every single event triggers an action, but sometimes running an action can be costly. For example, you set an event handle to trigger **Run query** action to update data in response to the **Click** event, but you find that query too expensive to run, then you can set a throttle time to let the query run only once within a given time.


# Write JavaScript


# Write JavaScript in {{ }}

When building apps in PocketBlocks, you can use JavaScript (JS) to access and transform data from objects, including components, queries, and global parameters. When writing JavaScript inside component property's input box, table column settings, etc., always remember to enclose all your JS code inside double curly braces, such as `{{'hello, ' + currentUser.name}}`.

## Access data

Objects have globally unique names, such as `input1`, `query1`, and `table1`. You can refer to the properties of the objects in your app by JS code.

### Access data in an object

PocketBlocks supports you accessing the data in an object using dot notation (`objectName.keyName`). For example,`{{userInfo.selectedRow.userName}}` accesses the `userName` value in the currently selected row of **Table** `userInfo`.

When writing JS in `{{ }}` to access values in an object, add a `.` after the object name to trigger an autosuggest menu in case you are not sure about objects' built-in properties or methods.

**Example**

This GIF shows how the dot notation triggers an autosuggest menu and displays the properties of `table1`.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-3b47b6b9935cfc67c6d87947da04a7f2d8f037a5%2F01.gif?alt=media" alt=""><figcaption></figcaption></figure>

### Access data in an array

You can access the values in an array by index. The index always starts at 0, so you can use `array[0]` to access the first element of the array.

**Example**

The **Data** property of **Table** component is an array of objects. This GIF shows how to access the value of `first_name` in the first element of the **data** array in `table1`.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-bdbf3a16a06e4d33da454e5207602e4ee4058611%2F02.gif?alt=media" alt=""><figcaption></figcaption></figure>

## Transform data

You can leverage built-in JS functions and third-party libraries in `{{ }}` to transform data, such as `filter()`, `map()` and `reduce()` operations.

**Examples**

Lowercase a string.

```javascript
{
  {
    input1.value.toLowerCase();
  }
}
```

Change date format.

```javascript
{
  {
    moment(table1.selectedRow.date_column).format("YYYY-MM-DD");
  }
}
```

Return name from query results.

```javascript
{{query1.data.map(i => i.name)}}.
```

## Restrictions

The JS code in `{{ }}` should be a single-line code, such as `.map()` or `.reduce()` combined with an arrow function or a ternary operator.

**Examples**

```javascript
{
  {
    query1.data.id.length;
  }
} // ✅ to reference a value
{
  {
    query1.data.map((row) => row.id);
  }
} // ✅ .map() + arrow function
{
  {
    num1 > num2 ? num1 : num2;
  }
} // ✅ ternary
```

The following JS code examples are illegal in `{{ }}`.

```javascript
{
  {
    // ❌ you can't write code like this in {{ }}
    const array = query1.data;
    const filterArray = array.filter((it) => it.value > 10);
    return filterArray;
  }
}
```

If you wish to orchestrate multiple lines of JavaScript, PocketBlocks supports you writing such code in [transformers](/build-apps/write-javascript/transformers).

```javascript
// codes inside a transformer
if (select.value === "1") {
  return "Option 1";
}
if (select.value === "2") {
  return "Option 2";
}
return "Option 3";
```

## View data

Data from queries can be complicated and nested in real cases. Viewing data provides you with the detailed structure of data in objects and helps you understand your data better. Before accessing or transforming data, you may need to view the data and its structure first. PocketBlocks offers three ways to view data.

### View query result

After running a query inside the query editor by clicking the **Run** button. Query result is displayed in the format shown below.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-8a79058dbcca6c1787164beb0954d4f06ca473a0%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### View data in Data Browser

Data browser located in the left pane displays all of the data inside your app. You can click on the node to expand and view the data structure.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-efc32ec4439a4803b4a408e8c47cf0e837b13b8f%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

### Real-time view

When setting up properties or writing JS code inside an editor, you can view the evaluated result in real-time in a box below your editor.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-9ca18ca65ef0389aac995890c6f897a6c7ae1fcc%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>


# JavaScript query

There are cases where you want to orchestrate operations, for instance, after triggering two queries, you want to combine and store their results to a temporary state, and then open a modal. This process can be complicated when chaining several event handlers, and certainly cannot be done in one line of code in `{{ }}`. That's where JavaScript (JS) query comes into play. It unleashes the ability to interact with components and queries by writing complex JS queries to achieve the following operations:

* Interact with UI components
* Trigger queries
* Access third-party JS libraries
* Customize functions

The following example is for you to quickly understand what JS query is and how it works.

## Return data

Use `return` syntax to return result. For example, the following code returns `3`.

```javascript
return Math.floor(3.4);
```

The result returned can also be a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) object. For example, `query2.run()` returns a Promise object.

```javascript
return query2.run();
```

{% hint style="info" %}
The `return` statement is not necessary for scenarios where you want to omit results.
{% endhint %}

## Access data

Use JS queries to access data in your app. Notice that there's no need to use `{{ }}` notation.

```javascript
var data = [input1.value, query1.data, fileUpload.files[0].name];
```

## Control component

In JS queries, you can use methods exposed by components to interact with UI components in your app. Such operation is not supported by the inline JS code in `{{}}`.

```javascript
// set the value of input1 to "Hello"
input1.setValue("Hello");
```

{% hint style="warning" %}
The `input1.setValue()` method (or other component methods) is asynchronous and returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) object. Accessing `input1.value` immediately after setting the value of `input1` does not return the updated value.
{% endhint %}

## Run query

### `run()` method and callbacks

Call `run()` method to run other queries, for example:

```javascript
return queryByName.run(); // run a query and it returns a Promise
```

The return value of `query.run()` is a Promise, so you can attach callbacks to handle the successful result or error.

```javascript
return queryByName.run().then(
  (data) => {
    // after query runs successfully
    return "hello, " + data.user_fullname;
  },
  (error) => {
    // after query runs in failure
    // use built-in message function to pop up an error message
    message.error("An error occured when fetching user: " + error.message);
  }
);
```

### Pass in parameters

You can pass parametes in the `run()` method to decouple query implementation from its parameters.

```javascript
query.run({
    param1: value1,
    param2: value2
    ...
});
```

## Declare a function

You can declare functions inside a JS query for better readability.

```javascript
// Whether the first number is a multiple of the second number
function isMultiple(num1, num2) {
  return num1 % num2 === 0;
}

// Call the moment library to return the current date
function getCurrentDate() {
  return moment().format("YYYY-MM-DD");
}
```

## Add preloaded scripts

PocketBlocks supports importing third-party JS libraries and adding predefined JS code, such as adding global methods or variables for reuse either at **app-level** or **workspace-level**. You can find the app-level settings in ⚙️ > **Other** > **Scripts and style**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-b9de9f654a7ee43bc6a0964505614b9c2fb0da74%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

For workspace-level, go to ⚙️ **Settings** > **Advanced**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-247f4d3c507eb744bad2414b828ee8a25cf93d79%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

In **JavaScript** tab, you can add preloaded JavaScript code to define global methods and variables and then reuse them in your app. For importing libraries, see [Use third-party libraries](/build-apps/write-javascript/use-third-party-libraries).

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-170b902259471f5bd095aac65d5be5e80a1d8235%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-814df3bf6a2c8983b8bdf0ae4d5818680a420d03%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

## Restrictions

For security reasons, several global variables and functions of **window** are disabled in PocketBlocks. Please report to our [GitHub](https://github.com/pedrozadotdev/pocketblocks) if you encounter any issues.


# Transformers

Transformers are designed for data transformation and reuse of your multi-line JavaScript code. Data from queries or components might not meet your needs in business scenarios. Also, you may use the same code block several times within an app. In such cases, a transformer is what you need.

Compared with inline code in `{{ }}`, transformer supports multi-line code blocks. And unlike JavaScript query, transformer is designed to do read-only operations, which means that you cannot trigger a query or update a temporary state inside a transformer.

## Quickstart

Click **+ New > Transfromer** in a query editor to create a transformer.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-2d5f20d4dc84c73647ef5257d365c0af4b3b538a%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Then write your JS code in the transformer. You can click **Preview** to get the return value and access it by `transformerName.value` in your app.

In the following example, `transformer1` uses the data of star rating in `rating1` to calculate a score.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-558da7dcf200fe832f95eb529c21b4d2fdc3d34f%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
`{{ }}` is disallowed inside a transformer or JS query. `{{ }}` is only used for the purpose of single-line JS expression, whereas a transformer or JS query is for multiple lines of JS code.
{% endhint %}

## Use cases

### Transform timestamp

Use the `moment().format()` method to transform timestamp formats. The following example converts the timestamp value of `start_time` returned by `query1` to `YYYY-MM-DD` format.

```javascript
return query1.data.map((it) => {
  return {
    ...it,
    start_time: moment(it.start_time).format("YYYY-MM-DD"),
  };
});
```

### Sort query data

Use the `_.orderBy()` method provided by [lodash](https://lodash.com/) to sort data. The following example returns `query1.data` sorted by `amount` column in ascending order.

```javascript
return _.orderBy(query1.data, "amount", "asc");
```

### Join two queries

The example code below shows how to join query results of `getUsers` and `getOrders` on user id.

```javascript
const users = getUsers.data;
const userOrders = getOrders.data;
return users.map((user) => ({
  ...user,
  orders: userOrders.find((order) => order.customer_id === user.id),
}));
```

## Read-only operations

Only read-only operations are allowed inside a transformer. It means that you cannot set values of components or temporary states, or trigger queries. For those operations, use JavaScript queries instead.

For example, you cannot call the method `setText()` of a text component in a transformer.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-b3e8cb516f20a41a129de4633a9570d8b4bb8d3d%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

Instead, calling the method `setText()` in a JavaScript query reports no error.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-ce903980ea2557602727ff9d8683f0df128561f7%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

In another example, transformer`sort1` aims at sorting the data of `getUsers` by `first_name`, but the `sort()` method may change the original data, so an error occurs.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-903b25440681539f13b8d3d9310ffae3403c1808%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

In this case, use the method `_.orderBy()` provided by [lodash](https://lodash.com/) instead.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-760e3a4024a421ac677aebce30b5f725da3fb3cb%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>


# Temporary state

You can use temporary state to store and reference local data within an app. Every time you load or refresh an app, the value of temporary state value is reset.

## Use case scenarios

Temporary states may help in the following scenarios:

* To track the temporary values of a variable when the user interacts with your app.
* To store your data only in operation without persisting to a database.
* To function as a temporary property when built-in properties in PocketBlocks (such as `{{table.selectedRow}}` and `{{select.value}}`) do not support your use case.

{% hint style="info" %}
To store and access data across apps in your workspace, use localStorage instead.
{% endhint %}

## Create a temporary state

Click **+ New** and select **Temporary state** in query editor.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-af21e42d8590fe1c47d9e4aa657773e4100e2ae5%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

You can rename the temporary state and set an initial value.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-43b528a5e6775200e05e0e5eda0f68f53b9d65e3%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

## Set state values

Temporary state offers `setValue()` and `setIn()` methods to set or change its value, which can be called in JavaScript queries.

Use `setValue()` to change the value directly.

```javascript
//state.setValue(value: any)
state.setValue(3);
state.setValue(input1.value);
```

When the initial value of a temporary state is an object, use `setIn()` to change the value in a specified path.

```javascript
// initial value of state2 as follows：
{
    girl: {
        name: "Lucy",
        age: 18,
        city: {
            name: "New York"
        }
     }
     boy: {
         name: "Bob",
         age: 21,
         city: {
             name: "Los Angeles"
         }
     }
}
//To change the value in a specified path
//state.setIn(path, any value)
//path: an array of keys or indexes. Only the last item in the path will be changed.
state2.setIn(['girl','city'],{name:'Seatle'})
state2.setIn(['boy','age'],18)


// To set value array value, you can use
// init value = ["hello", "world"]
state2.setIn([1],"foo") // this will result to ["hello", "foo"]
```

You can also call these two methods in [event handlers](/build-apps/event-handlers). Select **Set temporary state** as the action and choose method on demand.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-33aabacaf95efc0bb82e1c8a2002df398845671c%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

## Example: Increment counter

In this example, the counter tracks the number of button clicks. Every time the user clicks the button, the number in the text component increases by one.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-27cd7081b78fc5d80f7892a488ed66474931d17e%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

Build an increment counter in following steps:

1. Add a button component `button1` and a text component `text1`.
2. Create a temporary state `state1`, set its initial value as `0`. Bind `{{state1.value}}` as the display text of `text1`.

   <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-8d74b984f133658d234f13e698b9ec1153988783%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>
3. Add an event handler for `button1`. Select the action **Set temporary state** and the method **setValue**, and then set `{{state1.value+1}}` as the value.

   <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-80a8e3ad7472721bf453ae298bbe476ffd984091%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>
4. Click the button, you can see the value of `text1` increases by one each time you click.

   <figure><img src="https://github.com/internoapp/pocketblocks/blob/main/docs/.gitbook/assets/build-apps/write-javascript/temporary-state/07.png" alt=""><figcaption></figcaption></figure>

You can also achieve the same result using JavaScript queries:

1. Add a new query, select **Run JavaScript code**.
2. Write JavaScript query with this code, and set it to be manually invoked:\
   `state1.setValue(state1.value + 1)`
3. Add an event handler of `button1` to run `query1`.

   <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-e3fc9c462e0b2e860a365acece23ab566166d70f%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>

Now click the **Increment counter** button, you should see the same result as above.


# Data responder

When building an app, you can set events for the components in order to listen to the changes of certain data. For example, for a **Table** component, the built-in events for the change of the `selectedRow` property include "Row select change", "Filter change", "Sort change", and "Page change".

However, there lacks similar events for some data changes, such as the changes of temporary states, transformers, or query results. Data responders are designed for these cases and allow you to listen and respond to any data change.

{% hint style="info" %}
Events for data responders are more general than the events that listen to data changes such as content change, row select change, etc.
{% endhint %}

## Listen to data changes

In query editor, click **+ New**, and then select **Data responder** to create a new data responder.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-0cb25108b83cb9110814341ecf8e4000c7cd6af7%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

You can set the data that data responder listens to. It supports all kinds of data formats, including number, string, array, and JS object. In the following example, any value change in the **Text** component triggers a global notification.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-eb7510b411ad7e90a46d356da92f75d3e2b4c3e7%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

If the data is in array or JS object format, then data change from any sub-element will trigger the configured event. For example, the data of `dataResponder2` is a JS object, which listens to two **Input** components in the app. Data change of any component triggers the same global notification.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-3eae4971204c4d314d3b0f327f836336ef87ca67%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

## Respond actions

For detailed information, go to [Event handlers](/build-apps/event-handlers) > [Actions](/build-apps/event-handlers#actions).


# Built-in JavaScript functions

## utils - utility functions

### utils.openUrl()

Open a URL.

```javascript
// Syntax
utils.openUrl( url: string, options?: { newTab:  boolean = true } )
```

| Parameter      | Description                                                                                                                |
| -------------- | -------------------------------------------------------------------------------------------------------------------------- |
| <p>url<br></p> | Required. A **String** value that specifies the URL to open. It must start with *http\://* or *https\://*.                 |
| newTab         | Optional. **Boolean** value that, when **True**, specifies the url is to open in a new tab. The default value is **True**. |

```javascript
// Example: Open google.com in a new tab.
utils.openUrl("https://www.google.com", { newTab: true });
```

### utils.openApp()

Open an PocketBlocks app.

```javascript
// Syntax
utils.openApp( applicationId: string, options?: { queryParams?: {"key":"value"}, hashParams?: {"key":"value"}, newTab: true } )
```

| Parameter                                                 | Description                                                                                                                                                                                                                                                                                                                           |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p>appId<br></p>                                          | <p>Required. A <strong>String</strong> value that specifies the ID of the app to open.</p><p><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-00e5a0852de1eb4fadd5a387886f6c0b78d3a2c1%2F01.png?alt=media" alt="" data-size="original"></p> |
| queryParams: {'key1':'value1',key2:'value2',...}          | Optional. An **Object** that specifies query parameters to pass into the app. The query parameters are added to the app URL in the form of ?*key1=value1\&key2=value2&...*                                                                                                                                                            |
| <p>hashParams：{'key1':'value1',key2:'value2',...}<br></p> | Optional. An **Object** that specifies hash parameters to pass into the app. The hash parameters are added to the app URL in the form of *#key1=value1\&key2=value2&...*                                                                                                                                                              |
| newTab                                                    | Optional. A **Boolean** value that, when **True**, specifies the url is to open in a new tab. The default value is **True**.                                                                                                                                                                                                          |

```javascript
// Example: Open an PocketBlocks app in a new tab.
utils.openApp("632bddc33bb9722fb888f6c0", { newTab: true });

// Example: Open an PocketBlocks app and pass in "id" parameter.
utils.openApp("632bddc33bb9722fb888f6c0", {
  queryParams: { id: table1.selectedRow.id },
});
```

### utils.downloadFile()

Download a file containing the specified data.

```javascript
// Syntax
utils.downloadFile(data: any, fileName: string, options?: {
  fileType?: string,
  dataType?: "url" | "base64"
} )
```

| Parameter | Description                                                                                                                                                                                             |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| data      | Required. A **String** or **Object** that specifies the data to download from queries, components, transformers, etc.                                                                                   |
| fileName  | Required. A **String** value that specifies the name of the file to download.                                                                                                                           |
| fileType  | Optional. A **String** value that specifies the type of the file to download. All [MIME types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) are supported. |
| dataType  | Optional. A **String** value that specifies the type of the data: "url" or "base64".                                                                                                                    |

```javascript
// Example: Download the base64 data from a file component as a PNG file named users-data.
utils.downloadFile(file1.value[0], "users-data", {
  fileType: "png",
  dataType: "base64",
});

// Example: Download the results of query1 as a XLXS file named users-data.
utils.downloadFile(query1.data, "users-data", { fileType: "xlsx" });
// or in this way:
utils.downloadFile(query1.data, "users-data.xlsx");

// Example: Download the results of query1 as a XLXS file named users-data.
utils.downloadFile(restApiQuery.data, "users-data", {
  fileType: "pdf",
  dataType: "base64",
});
```

### utils.copyToClipboard()

Copy a string to clipboard.

```javascript
// Syntax
utils.copyToClipboard( text: string )
```

| Parameter | Description                                                      |
| --------- | ---------------------------------------------------------------- |
| text      | Required. A **String** value that specifies the content to copy. |

```javascript
// Example: Copy the content of input component to clipboard.
utils.copyToClipboard(input1.value);
```

## message - global notification

Use `message` methods to send a global alert notification, which displays at the top of the screen and lasts for 3 seconds by default. Each of the following four methods supports a unique display style.

```javascript
// message.info( text: string, options?: {duration: number = 3 } )
message.info("Please confirm your information", { duration: 10 });
// message.success( text: string, options?: {duration: number = 3 } )
message.success("Query runs successfully", { duration: 10 });
// message.warn( text: string, options?: {duration: number = 3 } )
message.warn("Warning", { duration: 10 });
// message.error( text: string, options?: {duration: number = 3 } )
message.error("Query runs with error", { duration: 10 });
```

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-bb0706b4f7bca60aa3f80cb617faed39d4702c66%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

## localStorage

Use `localStorage` methods to store and manage key-value pair data locally, which is not reset when the app refreshes, and can be accessed in any app within the workspace using `localStorage.values`.

| Method                             | Description                     |
| ---------------------------------- | ------------------------------- |
| setItem(*key: string, value: any*) | Store a key-value pair.         |
| removeItem(*key: string*)          | Delete a key-value pair.        |
| clear()                            | Clear all data in localStorage. |

### localStorage.values

You can access any key-value pair in local storage using `localStorage.values.` in JavaScript queries.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-9934ba4438d67b2f02e8224eb9f52c148be0e230%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

Inspect the data in localStorage in **Globals** in the data browser.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-ca0a38274adc7a5e702e2a487d6cf8a25ed62548%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

### localStorage.setItem()

Store a key-value pair.

```javascript
// Syntax
localStorage.setItem(key: string, value: any)

// Example
localStorage.setItem("order", select1.value)
```

### localStorage.removeItem()

Delete a key-value pair.

```javascript
// Syntax
localStorage.removeItem(key: string)

// Example
localStorage.removeItem("order")
```

### localStorage.clear()

Clear all data in localStorage.


# Use third-party libraries

Every developer learns one of the most important principles of software engineering early in their career: DRY (Don’t Repeat Yourself). Using third-party libraries can save your time as you do not need to develop the functionality that the library provides. PocketBlocks provides some built-in third-party libraries for common uses, and you can manually import other libraries on demand.

## Built-in libraries

PocketBlocks provides some JavaScript built-in libraries for use.

| Library                  | Docs                                                       | Version                    |
| ------------------------ | ---------------------------------------------------------- | -------------------------- |
| lodash                   | <https://lodash.com/docs/>                                 | 4.17.21                    |
| moment                   | <https://momentjs.com/docs/>                               | 2.29.3                     |
| uuid                     | <https://github.com/uuidjs/uuid>                           | 8.3.2（Support v1/v3/v4/v5） |
| numbro                   | <https://numbrojs.com/format.html>                         | 2.3.6                      |
| papaparse(Papa)          | <https://www.papaparse.com/docs>                           | 5.3.2                      |
| PocketBase SDK(pb)       | <https://pocketbase.io/docs/client-side-sdks>              | 0.21.3                     |
| TanStack QueryClient(qc) | <https://tanstack.com/query/v5/docs/reference/QueryClient> | 5.44.0                     |

## Manually import third-party libraries

PocketBlocks supports setting up preloaded JavaScript and libraries which can be at **app-level** or **workspace-level**.

* **App-level** libraries get loaded only in the app where defined. Plus, app A cannot use libraries that are set up for app B.
* **Workspace-level** libraries will be loaded when you open any application in your workspace. All the apps can access those libraries. There can be a certain impact on app performance, especially when you have complex JavaScript functions that aren't being used in every app.

{% hint style="info" %}
**Tips you should know before setting up libraries:**

* External libraries are loaded and run in the browser.
* NodeJS-only libraries are not supported now.
* URLs of external libraries need to support cross-domain.
* The export of the library must be set directly on the window object, global variables like `var xxx = xxx` do not take effect.
* The external libraries run in a restricted sandbox environment and the following global variables are not available:

  <mark style="background-color:yellow;">`parent`</mark>

  <mark style="background-color:yellow;">`document`</mark>

  <mark style="background-color:yellow;">`location`</mark>

  <mark style="background-color:yellow;">`chrome`</mark>

  <mark style="background-color:yellow;">`setTimeout`</mark>

  <mark style="background-color:yellow;">`fetch`</mark>

  <mark style="background-color:yellow;">`setInterval`</mark>

  <mark style="background-color:yellow;">`clearInterval`</mark>

  <mark style="background-color:yellow;">`setImmediate`</mark>

  <mark style="background-color:yellow;">`XMLHttpRequest`</mark>

  <mark style="background-color:yellow;">`importScripts`</mark>

  <mark style="background-color:yellow;">`Navigator`</mark>

  <mark style="background-color:yellow;">`MutationObserver`</mark>
  {% endhint %}

Now let's take **cowsay** as an example and import it at app-level and workspace-level.

* GitHub page: <https://github.com/piuccio/cowsay>
* Library link: <https://unpkg.com/cowsay@1.5.0/build/cowsay.umd.js>

### At app-level

Navigate to the settings page and then click the plus sign **+** under the **JavaScript library** tab. Paste the **cowsay** link and click **Add New**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-efa0e9d94a4b923fca1a7e60a69129a79bd4c576%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Create a JS query and insert code.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-7b4159f6aa9ecf480a18f11809278b6c39863433%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

You can obtain the same result by calling the `cowsay.say()` method in the value of the text component.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-983783686b7e8dcba1845c8925a7dbda15c91c26%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

Note that the cowsay library is imported at app-level and you can not use it in any other app within your workspace.

### At workspace-level

Go to PocketBlocks Homepage, select **Settings** > **Advanced**, and then click **Add** under the **JavaScript library** tab. Paste the link of the third-party JS library and click **Add New** to add it to your workspace. The installed libraries are accessible from any app within your workspace.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-15db33a7fa64f2210f7c27deb5153943476b2aa9%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>


# Component guides


# Option lists

A drop menu ensures easy and error-free user input by offering a list of possible options. PocketBlocks supports implementing option lists using components such as **Select** and **Multiselect**. You can configure an option list either manually or by mapping data from your data sources.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-fa478a3ded8dbc5080636e789acfdb79e1201f84%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

## Properties

Each option list has four properties.

* **Label**: the displayed text of the option to users
* **Value**: the unique identifier of the option
* **Disabled**: disable the option (the default value is `false`)
* **Hidden**: hide the option (the default value is `false`)

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-9a2d3d0ff354754fdfc265140ca63d399662494c%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
When more than one option in one list uses the same value, only the first option is valid and thus displayed.
{% endhint %}

## Manual mode

Under **Basic** > **Manual**, click **+ Add** to create a new option. Select an option to manually configure it. You can click `···` to **Duplicate** or **Delete** an option and drag `⋮⋮` to arrange its position.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-03142b278b4923047bd088a735be13043b839075%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

Check the value of the selected option under **Components** in the data browser. For example, when **New York** is selected, you can find the string value `"1"` for **locationSelect**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-9305c141912c192f2c099034287c24ed0dfd118e%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

Manual mode is recommended for these scenarios:

* Manually manageable and enumerable.
* Used by only one component.
* Data doesn't come from data sources.

## Mapped mode

When you have option list data that comes from data sources, transformers or temporary state, you can use **Mapped Mode**. Under **Basic** > **Mapped**, input your data source array in **Data** box using JavaScript (JS) code. A list of options will be automatically mapped from this array. For example, access university information via `{{university.data}}`. Each item in the result array contains `country`, `web_pages`, `alpha_two_code`, and `name`.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-6626d935e8babeb656a64429c2c908c06ca961ef%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

You can reference the value of any filed of an option through `item` and its index `i`, starting from 0. In the following example, the **Label** of each option is the `name` of the university, the **Value** is the `web_page`, and those containing an opening parenthesis `(` in their names are disabled. The default value is set to the `web_pages` of the first item using `{{university.data[0].web_pages}}`. Note that the default value of an option list should be an element from the **Value** array but not the **Label** array.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-88182c7047eba7fe0cd49af9fd090f3db271f426%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

Check the value of the selected option under **Components** in the data browser. For example, when "Ahi Evran University" is selected, its string value `[\"http://www.ahievran.edu.tr/\"]` is displayed.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-42816198a31d64ef9dc7f66f5236237c840494ee%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>


# List View

The component List View is for you to display rows of data. It works like a container: you can insert other components into it and bind data to these components.

The component **List View** displays rows of data. Similar to Form, Modal, and Drawer, it is also a container-like component that can hold other components or modules. For list viewing data, you first bind the data to a **List View** component and configure the naming rules for the items. Then, you design the display of the first row by dragging and dropping components, and this layout will be applied to all items within this component.

The following is a demo of **List View**, displaying part of BEST BOOKS OF 2021 from [Goodreads](https://www.goodreads.com/choiceawards/best-books-2021):

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-91b66edb1a7a6b899afed0ad5c1598594adef4c8%2F01.gif?alt=media" alt=""><figcaption></figcaption></figure>

Drag and drop **List View** onto the canvas. Each item contains an **Image**, a **Text** and a **Rating** component. You can update the exhibition of the whole **List View** component by configuring the layout of the first entry.

Click the **Image** component, you see the defaulted image source.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-0d76d350c550482ba95a4e06cf6961083bff2bcc%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

The **List View** component retrieves data from a JSON array of objects and displays an **Image**, a **Text** and a **Rating** component for each entry. You can also pass query results to a **List View**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-b28fda2639f66f65a338092fe81c1796c2774386%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

## Bind data

The data of a **List View** component accepts two types of values: number and array.

* Number: Numbers are processed as row count and no valid data is passed into the **List View** component.
* Array: The length of an array is passed as row count and each entry in the array is processed as a JS object in JSON format, corresponding to a row in the **List View** component. For example, the following data contains two rows of data, each containing four fields: `rate`, `title`, `url`, and `cover`.

```json
[
  {
    "rate": "9.2",
    "title": "The Shawshank Redemption",
    "url": "https://www.imdb.com/title/tt0111161/",
    "cover": "https://m.media-amazon.com/images/M/MV5BMDFkYTc0MGEtZmNhMC00ZDIzLWFmNTEtODM1ZmRlYWMwMWFmXkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_UY67_CR0,0,45,67_AL_.jpg"
  },
  {
    "rate": "9.2",
    "title": "The Godfather",
    "url": "https://www.imdb.com/title/tt0068646/",
    "cover": "https://m.media-amazon.com/images/M/MV5BM2MyNjYxNmUtYTAwNi00MTYxLWJmNWYtYzZlODY3ZTk3OTFlXkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_UY67_CR1,0,45,67_AL_.jpg"
  }
]
```

You can view the detailed data about the **List View** component, its items, the properties, etc., in the data browser.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-b402a4c8aad35da5e4e09ce71135caf894252fd7%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-32530fd8afda0dd7aa665bb0aba711a2143d5b91%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

## Display data in inside components

After binding valid data to **List View** component and designing its inside components, you can add data to these components. **List View** supports local variables `currentItem` and `i`. Notice that you only need to change data of the first row, and the same settings are applied to the other rows automatically.

{% hint style="info" %}
You can bind a static URL address to the **Image** component for image display; and because that URL address is static, the same image shows up in all rows.
{% endhint %}

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-979603a2c59fb4e3c4c3bd46e72f60425a36658a%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

## Name items

You can set the item index names and item data names. This is useful when embedding a list in another list. For example, you can set the index of one list as `i`, and the inner nested `j` to avoid naming conflict.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-17eb20ad5a7e7ac1727c511591d03fad9ec3facf%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>

### Item index name

By default, item index is named as`i`, referring to the index of list data and starting from zero. Besides using `i` as numbers, you can also use `i` to dynamically access data from query results.

For example, to access the `book_name` field from table `fiction` in the **Text** component, write the following code.

```javascript
{
  {
    getAllFictions.data[i].book_name;
  }
}
```

Then you can see the fiction book names displayed in **List View** by index order.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-b3b05d6b1208396c6f90c771b2d067cc55b9f0da%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>

### Item data name

By default, you can reference the value of each item within a list using variable `currentItem`. For example, to display a serial number plus book name, write the following code in `text1` value.

```javascript
{{i+1}}. {{currentItem.book_name}}
```

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-2c5175b05636ee1e30bcdb08ab7a6601e0f4d006%2F09.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Circular dependency errors occur when you reference the data of a row by `listView.items[i]` from a component inside a **List View** component. It is recommended to use such reference only outside the list.
{% endhint %}

## Pagination

### Quick jumper

Toggle "Show quick jumper" or set its value to `true` to allow your users quickly jump to the specified page.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-69f2526e7cc83ec413559dc3e2bafd8dfc90c99f%2F10.png?alt=media" alt=""><figcaption></figcaption></figure>

### Page size

You can configure whether to allow your users to customize how many items to be displayed on a single page by enabling or disabling the "Show size changer button" or set its value in JS. When disabled, you can set the default page size.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-d08cfc0aa055b032166318577ad28900be988fb1%2F11.png?alt=media" alt=""><figcaption></figcaption></figure>

If enabled, you can configure several page sizes for your users to select.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-80b32ab743ab32945e7a049e7aedcdec38001fdf%2F12.png?alt=media" alt=""><figcaption></figcaption></figure>

### Total row count

By default, the total row count of a **List View** component is the number of current data items. You can also insert a value from a query. For example, `{{query1.data[0].count}}`.

## Reference List View items outside

**List View** supports exposing data of inside components with **Items** field. You can inspect the **Data Browser** in the left pane.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-c1d97560e602a04ff715fdef42aaddffbeb8d58b%2F13.png?alt=media" alt=""><figcaption></figcaption></figure>

For example, drag an **Input** component into **List View**, and then you can reference the value of the **Rating** component in components outside the **List View** by the following code.

```javascript
{
  {
    listView1.items[0].rating1.value;
  }
}
```

<figure><img src="https://github.com/internoapp/pocketblocks/blob/main/docs/build-apps/.gitbook/assets/build-apps/component-guides/list-view/14.png" alt=""><figcaption></figcaption></figure>


# Drawer

In PocketBlocks, **Drawer** is an overlay sidebar to display information or perform operations, without interrupting the workflow on the main window.

The following example builds a shopping cart using a drawer.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-44b6735b27a655318d844b4cbee727c44bd09cb3%2F01.gif?alt=media" alt=""><figcaption></figcaption></figure>

## Layout

When inserted by drag-and-drop operation, a **Drawer** floats on the right side (by default) of the main window. Then, you can add components onto the **Drawer** according to your needs. In the editing mode of a **Drawer**, other components on the canvas are not editable.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-9c2897af1112decde715ae9966ab0ad30c456c2a%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
When a drawer is closed, you can re-open it by clicking the corresponding label in the **Modals** tab in the left pane.
{% endhint %}

### Position

In the **Properties** tab, you can set the position of the drawer. The default position is the right side of the main window.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-60c86dbce46602c951a86dffb6a00f4ff97d9412%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### Resize

In **Properties** tab, you can set the width of the drawer by pixels or percentage. Note that the height of a drawer is the same as the main window and is not customizable.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-8c2defeb4c6b8f0fc8fbd6be1a6a0c4f950c3e07%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

## Events

You can reference a drawer in JS code anywhere in your app or call it through a "control component" action in **Properties** > **Interaction** > **Event handlers**.

The following sections guide you through how to open and close a drawer by clicking a button in an online shopping app.

### Trigger openDrawer

Usually, in an app, you trigger opening a drawer by an event such as clicking a button. For example, opening a drawer to display the shopping cart is implemented in the following steps.

1. Add a button and rename it as `gotoCart`.
2. Set the event handler of the button. Select "Control component" as the **Action** and select the component "cart" and method "openDrawer". All these settings are auto-saved.

   <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-7821071c8dfc0d19ff1872edf12e3c9d4a810c85%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>
3. Click the button `gotoCart` and the binded drawer "cart" is open.

### Trigger closeDrawer

Triggerring "closeDrawer" is similar to triggering "openDrawer". When setting up the event handler, select the method "closeDrawer". For example, closing a drawer that displays the shopping cart is implemented in the following steps.

1. Add a button and rename it as `gobackShopping`.
2. Set the event handler of the button. Select "Control component" as the **Action** and select the component "cart" and method "closeDrawer". All these settings are auto-saved.

   <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-4f602ff0373e1773e634a0c6eddadccd5ed27fc7%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>
3. Click the "Continue Shopping" button and the binded drawer "cart" is closed.


# Image

Use the **Image** component to present information in your apps in a vivic way. PocketBlocks supports you adding an image via URL and base64 encoded data.

## URL

Drag the **Image** component onto the canvas or into a **Container**. Click the **Image** component, and the **Properties** tab is displayed on the right. You can set the URL to display an image.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-c1a89d777a1c25e9db7c3383f008cf6d133a1634%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

## Base64 encoded data

You can also insert an image via base64 encoded data. Ensure that the encoded image source starts with `data:image/PICTURE_FORMAT;base64,` or simply`data:image;base64,`.

{% hint style="warning" %}
Don't miss the comma at the end of the prefix:

<mark style="background-color:yellow;">`data:image/PICTURE_FORMAT;base64`</mark><mark style="background-color:yellow;">**`,`**</mark><mark style="background-color:yellow;">`YOUR_BASE64_ENCODED_IMAGE_DATA`</mark>

<mark style="background-color:yellow;">`data:image;base64`</mark><mark style="background-color:yellow;">**`,`**</mark><mark style="background-color:yellow;">`YOUR_BASE64_ENCODED_IMAGE_DATA`</mark>
{% endhint %}

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-15d74088204212f3856431e58bd13ef5378a3e06%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

### Demo: upload and display an image

One common use case for base64 image display would be combining a **File Upload** component with an **Image** component.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-b87fb138d00f2f2b1eb0e76d32f09d0259849f5f%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

Here is JS code that concatenates the prefix with the encoded base64 data of the uploaded file via `file1.value[0]`.

```javascript
{
  {
    "data:image/jpeg;base64," + file1.value[0];
  }
}
```

## Set click preview for an image

Toggle **Support click preview** in the **Properties** tab to allow users to preview the image in its full size. Hover your mouse over the image, and you see **👁 Preview**. Then, you can click to preview.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-981bae349627378e062905c0be29681c7e77ec2e%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

## Set the style of an image

In **Properties** > **Style**, change border color and set **Border radius** in pixels or by percentage.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-0699ab5484a4d9c9fed8c80390acb1f71d646755%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>


# Charts and graphs

Charts and graphs are visual representations of data that are used to simplify complex information and make it easier to understand. They can help highlight key insights and provide a quick summary of data that would otherwise be difficult to interpret. Charts and graphs come in different forms, such as bar graphs, line graphs, pie charts, scatter plots, and more, each suited for different types of data and analytical purposes.

PocketBlocks allows you to insert multiple forms of charts and graphs into your apps to satisfy your needs in different use cases.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-70b97ee672992652a80e1287c2ddf5046da63584%2F01.gif?alt=media" alt=""><figcaption></figcaption></figure>

## UI mode

### Data format

In UI mode, the **Chart** component supports presenting data stored as an array of JS objects. Each object field corresponds to a column in tabular format. The objects in the following array contain three fields: `date`, `fruit`, and `count`.

```json
[
  { "date": "2022-03-01", "fruit": "apple", "count": 4 },
  { "date": "2022-03-01", "fruit": "banana", "count": 6 },
  { "date": "2022-04-01", "fruit": "grape", "count": 10 },
  { "date": "2022-04-01", "fruit": "apple", "count": 3 },
  { "date": "2022-04-01", "fruit": "banana", "count": 2 }
]
```

You can also use JS code in `{{}}` to reference data from other components or queries, or to transform data to meet specific needs.

For example, the query result of `query1` is as follows.

```json
{
  "date": [
    "2022-03-01",
    "2022-03-01",
    "2022-04-01",
    "2022-04-01",
    "2022-04-01"
  ],
  "fruit": ["apple", "banana", "grape", "apple", "banana"],
  "count": [4, 6, 10, 3, 2]
}
```

You can transform it using transformer `transformer1` with the following JS code.

```javascript
let dates = query1.data.date;
let fruits = query1.data.fruit;
let counts = query1.data.count;
let result = [];
for (let i = 0; i < dates.length; i++) {
  result.push({ date: dates[i], fruit: fruits[i], count: counts[i] });
}
return result;
```

Then reference the value of the transformer `{{transformer1.value}}` as the data for the chart.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-c5f78c77975e75dd06a8eeb3690f35a1a06dff57%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

### Chart type

PocketBlocks supports four types of charts: bar chart, line chart, scatter chart, and pie chart. You can select the chart type in **Properties** > **Data** > **Chart type**. You can also customize the layout and style of your chart in **Properties** tab.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-e9e1f265ee8c3b79146b21fd6a9c913a69b11677%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### X-axis

Bar charts, line charts, and pie charts map values to categorical variables. Thus, in such charts, the X-axis usually shows non-numeric data—for example, date or department.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-900a9cd6fe91d0742f1c62eae8ed93f35c6e4bb3%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

By default, PocketBlocks automatically detects the X-axis data and its type. You can also manually select one among "Category axis", "Value axis", "Time axis", or "Log axis". For detailed information, see [X axis type](https://echarts.apache.org/en/option.html#xAxis.type).

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-e372b134378c0a0898bd8d50daca49b5cf93e3ee%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

### Chart series

In most types of charts, the **Chart series** (Y-axis) presents numeric values for the categories on X-axis. By default, PocketBlocks populates all numeric fields to Y-axis. You can hide unnecessary fields in **Properties** > **Chart series**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-2fdc87184f9009da81a29108e8de32589fec1d60%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

## Echarts JSON

Apart from the built-in charts and graphs, you can also plot your data with [Apache ECharts](https://echarts.apache.org/en/index.html), an open-source JS visualization library. You only need to complete the **Configuration** > **Option** field in JSON format. For detailed information, see [ECharts docs](https://echarts.apache.org/en/option.html#title) and [ECharts examples](https://echarts.apache.org/examples/en/index.html).

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-50ce7d33d5414be7e1fd94a00603e6634f576cd7%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>

If you need more configuration options for charts, create a issue on [Github](https://github.com/pedrozadotdev/pocketblocks/issues).


# File upload

## Basics

You can customize the properties of the file upload components in the right panel, such as the displayed text, file types, upload type.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-9477baa0cc92ad40f14b400e047ff9bc48a8e7b6%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

### File type

You can input an array of strings to restrict the types of the files to be uploaded. The default value of file type is empty, meaning that no limitation is pre-defined. Each string value in a specified file type array should be a [unique file type specifier](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#unique_file_type_specifiers) in one of the following formats.

* A valid case-insensitive filename extension, starting with a period character ("."), such as `.png`, `.txt`, and `.pdf`.
* A valid string in [MIME format](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) without an extension.
* String `audio/*` indicating "any audio file".
* String `video/*` indicating "any video file".
* String `image/*` indicating "any image file".

For example, when the value of file type is `[".pdf", ".mp4", "image/*"]`, you can upload PDF files, MP4 files, and any type of image files.

### Upload type

You can decide whether to upload a single file, multiple files, or a directory.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-9f66e6420a5047c59444144cc36032c113f85526%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

### Display uploaded files

Switch on or off **Show upload list** to display or hide the list of the uploaded files. You can also set this property via JS code. By default, its value is "true".

The upload list presents the file names of all uploaded files in chronological order. You can also access the name of the uploaded files via the property `files[index].name`. When hovering your mouse over a file, the 🗑️ icon appears and you can click it to delete the corresponding file.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-2f5313fa437c165c4aafff215aaa18506e330d03%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### Parse files

Toggle **Parse files** and PocketBlocks will try to parse the uploaded file data structure into objects, arrays, or strings. You can access the parsed result via the property `parsedValue`. PocketBlocks supports parsing Excel, JSON, and CSV files. The parsing result of other types of files is `null`.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-5bcbe9c9162064e0b52505435d229f4d72900d99%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

## Validation

Under the validation tab, you can configure how many files are allowed to be uploaded, as well as the minimum and maximum size of a single file to be uploaded.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-dfb5c5c64ecb6ba70db53e06392dc21f59b9377d%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

### Max files

When the upload type is "Multiple" or "Directory", you can set **Max files** to limit the maximum number of files to upload. If the number of files to be uploaded exceeds this threshold, the latest uploaded files will replace the oldest ones.

### File size

You can set the minimum and maximum size of the files to upload, using KB, MB, GB, or TB units. The default unit for file size is byte.When the size of the uploaded file exceeds the limit, you will see a global alert.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-d4458ed294bf11fc27f23a4e9dbc41eb7c91e838%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

### Access uploaded files

Files uploaded via the file upload component are stored in browser cache memory in **base64-encoded** string format. To store these files in data sources, you need to build queries to connect to databases or APIs.You can view the properties of the uploaded files in the data browser in the left pane, or access property names in `{{}}` or JS queries via JS code. Commonly used properties are as follows.

* `value`: A list of the content of the uploaded files, encoded in base64.
* `files`: A list of metadata of the uploaded files, including `uid`, `name`, `type`, `size`, and `lastModified`.
* `parsedValue`: A list of the value of the parsed files.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-f1ec0b7ce2fb3d777d45f24c437381bc1191b60d%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>


# Custom component

In PocketBlocks, you can design custom components using React.js library to satisfy specific needs when building your app. The custom component can be static or dynamic, but either requires coding.

## Prerequisites

* Good understanding of how to build an app in PocketBlocks.
* Familiar with HTML/CSS/JS and the React.js library.

## Basics

Drag a **Custom component** onto the canvas. By default, PocketBlocks adds a title box, a text box, and two buttons into it, as shown below. You can modify **Data** and **Code** in the **Properties** pane to tailor it according to your requirements.

{% hint style="info" %}
Click the border instead of the inside area to select a **Custom component** and display its property settings.
{% endhint %}

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-4ebe459d87bacbeecada740113acd657b23c4498%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

### Data

**Data** stores information in key-value pairs, providing an interface for the **Custom component** to interact with data outside it. For instance, you can reference data of the **Custom component** in other components in your app via `customComponentName.model`, or pass data from other components to the **Custom component**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-fffcc9fbe23f3e17d387d2b4756b7e3c6195687e%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

### Code

By default, PocketBlocks defines the object `model`, and two functions `runQuery` and `updateModel`.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-cae4eab9f486e6493cfc680571de1887f9e8679e%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

* `runQuery` is a function that accepts a query name in string format. For example, `runQuery(model.query)`.
* `updateModel` is a function that accepts a single argument of object type. The argument passed to `updateModel` will be merged with data of the **Custom component**.

## Implementation

All code of your **Custom component**, including HTML, CSS, and JavaScript, stores in the **Code** box in the **Properties** pane. When your app runs, the custom component will be embedded into an [iframe](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe) element.To facilitate the interaction between the **Custom component** and other components in your app, PocketBlocks offers an API for you through global objects. The type definition and description of the objects are as follows.

```javascript
interface PBL {
  // Subscribe to data change
  // When data changes, handler will be triggered
  // The returned value is the unsubscribe function
  subscribe(handler: SubscribeHandler): () => void;
  // React HOC component function that accepts a React component
  // Return a new component that contains properties: runQuery, model, updateModel
  connect(Component: ComponentType<any>): ComponentType;
  // Run the specified query
  runQuery(queryName: string): Promise<void>;
  // Update data
  updateModel(patch: any): Promise<any>;
}

interface SubscribeHandler {
  (data: IDataPayload): void;
}

interface IDataPayload {
  model: any;
}
```

The following example is the least code that a custom component requires to work.

```javascript
<div id="react"></div>
<script type="text/babel">
    const MyCustomComponent = ({ runQuery, model, updateModel }) => (
        <p>Hello, world!</p>
    );
    const ConnectedComponent = pbl.connect(MyCustomComponent);
    ReactDOM.render(<ConnectedComponent />,
document.getElementById("react"));
</script>
```

## Data interaction

### Pass data from app to custom component

For instance, to pass the text in an input box to a custom component, you can use the `{{}}` syntax to reference data from this **Text** component. Note that you can also reference data from queries in the same way.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-09d51ab907885c396e7422b4c82ea97402891764%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

Below is the code for this example.

```javascript
<div id="root"></div>

<script type="text/babel">

  const { Button, Card, Space } = antd;

  const MyCustomComponent = ({ runQuery, model, updateModel}) => (
    <Card title={"Hello, " + model.name}>
        <p>{model.text}</p>
        <Space>
          <Button
            type="primary"
            onClick={() => runQuery(model.query)}
         >
            Trigger query
          </Button>
          <Button
            onClick={() => updateModel({ text: "I'm also in a good mood!" })}
          >
          Update data
          </Button>
      </Space>
    </Card>
  );

  const ConnectedComponent = pbl.connect(MyCustomComponent);

  const root = ReactDOM.createRoot(document.getElementById("root"));
  root.render(<ConnectedComponent />);

  </script>
```

### Pass data from custom component to app

For instance, to display certain text from the **Custom component** in an **Input** component in the app, you can set the value of `custom1.model.name` as the default value of `input1`. The dot notation `custom1.model.name` accesses the name of the **Custom component**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-af9ff85cda451bd27c595d6cafb2e3cdceec9bde%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

### Trigger query from custom component

For instance, given table `users` which displays information of all users, you want to filter data based on the inputted text in a **Custom component**. Besides, the filter operation is triggered by clicking a button inside the same **Custom component**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-b6d5e2998f3916fced84f976b4f965e122cca85d%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

According to the requirement, the **Custom component** contains an **Input** component and a **Button** component. You can also add a **Text** component to provide context to the users of your app. When a user inputs into the text box, for example "Lor", and then clicks the search button, the table only presents the entries in which the "Name" field contains "Lor".

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-19256a2ff9c368215ab3a759d29794c913c3b2a6%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>

To implement such a **Custom component**, first you create query `filterUser` to access data from the custom component and set it to run by manual invoke.

```javascript
return users.value.filter(u => u.name.includes(custom1.model.search || ""));
```

Then, you import the "antd" library and use the components **Button**, **Input**, **Card**, and **Space**. Finally, one more setting for each component inside the **Custom component**:

* Configure the `updateModel` method to run and update the data of the **Custom component** when the text in the **Input** component changes.
* Trigger the query `filterUser` by the `runQuery` method when the **Search** button is clicked.

```javascript
<style type="text/css">
  body {
    padding: 5px;
  }
</style>

<link rel="stylesheet" type="text/css" href="https://unpkg.com/antd@4.21.4/dist/antd.min.css"/>

<script type="text/javascript" src="https://unpkg.com/antd@4.21.4/dist/antd.min.js" ></script>

  <div id="root"></div>

<script type="text/babel">

  const { Button, Card, Input, Space } = antd;

  const MyCustomComponent = ({ runQuery, model, updateModel}) => (
    <Card title={"Hello, " + model.name + " filters data for you!"}>

        <Space>
      <Input
          value={model.search}
          onChange={e => updateModel({ search: e.target.value})}
          placeholder="Input a name"
        />
          <Button
            type="primary"
            onClick={() => runQuery("filterUser")}
         >
            Search
          </Button>

      </Space>
    </Card>
  );

  const ConnectedComponent = pbl.connect(MyCustomComponent);

  const root = ReactDOM.createRoot(document.getElementById("root"));
  root.render(<ConnectedComponent />);

</script>
```


# Use Markdown

PocketBlocks supports you using the lightweight markup language Markdown to format texts in your app, such as changing the font size, inserting code, and adding a list. You can also embed HTML-formatted text in Markdown for more styling options.

Use Markdown in **Text** and **Table** components.

* **Text**: Use Markdown for the input text.

  <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-c07a890503c0c484350cfc51332230e7e2c48392%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>
* **Table**: Use Markdown for column type.

  <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-2b66775776f2fada22de18f380fa266a8d1cacfe%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

## Markdown basics

All Markdown syntax is valid in PocketBlocks.

* **Headings**: Use hashtag (#) before heading. More hashtags, lower heading level.
* **Paragraphs**: Use a blank line to separate texts into paragraphs.
* **Line breaks**: Add at least two whitespaces at the end of a line and press **Enter** to start a new line.
* **Emphasis**: Use single asterisk (∗) before and after text to convert it to *italic* text, double asterisks (∗∗) for **bold** text, and triple asterisks (∗∗∗) for ***italic bold*** text.
* **Blockquotes**: Use the closing angle bracket (>) to create a blockquote.
* **Lists**: Use hyphen (-), asterisk (∗), or plus sign (+) followed by a whitespace to create an unordered list, and use numbers followed by a period (.) to create an ordered list.
* **Code**: Use backticks (\`) before and after code to denote `` `code` `` in plain text, and three backticks (\`\`\`) to present ` ```code block``` `.
* **Horizontal rules**: Use at least three asterisks (∗∗∗), hyphens (---), or underscores (\_ \_ \_) at the beginning of a line to create a horizontal rule.
* **Links**: Use square brackets (\[]) for the display text and parenthesis (()) for the link address. Note that no space should be inbetween. For example, `[PocketBlocks](https://github.com/pedrozadotdev/pocketblocks)`.
* **Images**: Use an exclamation mark (!) to start an image shiinsertion, and then use square bracket (\[]) for the alternative text and parenthesis (()) for the link address or source path. The caption can follow the parentheses or start at a new line.
* **Escaping characters**: Use backslash (\\) to display the special symbols that Markdown uses. For instance, to print ` `` ` in plain text, you should use `` \`\` `` in Markdown.

For more information, see [Markdown guide](https://www.markdownguide.org/basic-syntax/).

## GFM extension

You can also use GitHub Flavored Markdown (GFM) extensions for additional syntax.

* **Footnotes**: Use caret (^) and number in square brackets (\[]) to insert footnotes. For more information, see [Footnotes](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#footnotes).
* **Strikethrough lines**: Use double tilde (\~\~) before and after text to add strikethrough lines. For more information, see [Styling text](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#styling-text).
* **Tables**: Use hyphens (-) separated by the vertical bar (|) to create the header row of a table, and continue using the vertical bar to separate content in cells. For more information, see [Tables (extension)](https://github.github.com/gfm/#tables-extension-).
* **Task lists**: Use a whitespace in square brackets (\[ ]) within the list format to create task lists. To mark a task completed, replace the whitespace with the letter *x*. For more information, see [Task lists](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#task-lists).

## HTML support

In PocketBlocks, you can use most HTML tags and properties. For more information, see [Embed HTML in Markdown](https://www.markdownguide.org/basic-syntax/#html).

{% hint style="warning" %}
For security reasons, a few HTML tags including **iframe** and **script** are not permitted in PocketBlocks.
{% endhint %}

### Appendix: Supported HTML tags

```html
<h1>
<h2>
<h3>
<h4>
<h5>
<h6>
<br>
<b>
<i>
<strong>
<em>
<a>
<pre>
<code>
<img>
<tt>
<div>
<ins>
<del>
<sup>
<sub>
<p>
<ol>
<ul>
<table>
<thead>
<tbody>
<tfoot>
<blockquote>
<dl>
<dt>
<dd>
<kbd>
<q>
<samp>
<var>
<hr>
<ruby>
<rt>
<rp>
<li>
<tr>
<td>
<th>
<s>
<strike>
<summary>
<details>
<caption>
<figure>
<figcaption>
<abbr>
<bdo>
<cite>
<dfn>
<mark>
<small>
<span>
<time>
<wbr>
<input>
```


# Module

When building an app, you want to reuse components and queries across different apps. Modules are what you need. A module comprises components and queries. You can insert a module into an app or other modules (referred to as *external apps* in the rest of this document) and it functions just like a single component.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-890de16454f06e2c138f2b045955907d67139857%2F01.png?alt=media" alt=""><figcaption><p>Build a <a href="#demo-a-statistics-module">statistics module</a></p></figcaption></figure>

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-05e9f72fdf4d1f73fd84be95e23000fe44ec2251%2F02.png?alt=media" alt=""><figcaption><p>Reuse this module anywhere</p></figcaption></figure>

## Module basics

### Create a new module

Select **New > Module** at the top right of homepage to enter the module editor.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-854860101985df5ebcafcdbbc0a038c4ea465ab1%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### Configure module settings

You can configure a module's settings in the **Settings** tab of data browser:

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-720dc2fca115fed1e70cb86f5d345710e32a9945%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

* **Input**: parameters passed into the current module from external apps.

  <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-60bdafd19000a49c5b5c9c3ab3f1bbcf15a1fff2%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>
* **Output**: data exposed to external apps.

  <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-4b45079f233bd3134e6fbd92879e33a8df52e77a%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>
* **Method**: methods exposed to external apps. For example, you can define a module with a `resetTitle` method, so that external apps can call it to reset the module's title.

  <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-571ba46a9f6499a2328dd4b886f2123685e61414%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>
* **Event**: module events can be handled by external apps. For example, you can define an event named `dataChanged`, so that external apps can add event handlers to it once the `dataChanged` event is fired by the module.

  <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-6fa489082bce78b85ffe5978edc74e31a024b03a%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>

For more details, check out chapter [Module settings](#module-settings).

### Design module UI

The other areas of the module editor are similar to those of the web app editor. Insert components and create queries the same way as your app-building process.In the module editor, you can resize a module by dragging the bottom-right corner to the desirable default size. Toggle the button in the **Properties** panel to control whether the **component height scales with the container**. \*\*\*\* This only works for the fixed-height components within the module.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-38b1a21d2922722098c8585bc52fd03ba2a86ca6%2F09.gif?alt=media" alt=""><figcaption></figcaption></figure>

### Insert module to apps or other modules

When editing an app or module, select **Insert > Extensions > Modules** to display the modules that you have access to.

<img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-0c9d4991661376842fbd72e0a607c56b29c156f0%2F10.png?alt=media" alt="" data-size="original">

Then drag and drop the module onto the canvas, and set input parameters, change styles inside the module's **Properties** panel.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-b75855407c7d55ef196af62656c647ed2cc02ea4%2F11.png?alt=media" alt=""><figcaption></figcaption></figure>

Inspect the data exposed by the module in the data browser.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-c738411e9a46167837d7b017305d1b80ed20ef61%2F12.png?alt=media" alt=""><figcaption></figcaption></figure>

## Module settings

### Input

Module inputs are parameters passed to the module from external apps. The supported input types are **data**, **string**, **number**, **array**, **boolean**, \*\*\*\* and **query**. The first five are data types. Choose **data** to not restrict it to a specific data type. When choosing the type of **query**, you can pass in a query from external apps and trigger it inside the module.Then you can reference a module input parameter by its \*\*name\*\*.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-2bf87506566a10d786cfe3e939aaa14a3ead2d8d%2F13.png?alt=media" alt=""><figcaption></figcaption></figure>

### Demo: A statistics module

This section guides you through the steps to build a statistics module and reuse it in an app.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-05e9f72fdf4d1f73fd84be95e23000fe44ec2251%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

1. Create module inputs:

   In the **Settings** tab, click **+** **Add** to create a new module input, and then set its **name**, **type**, **default value** (optional) and **tooltip** (optional). In this example, three module inputs are added: two string inputs `title`, `imageUrl`, and a number input `count`:

   <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-e5a5441d675834f03a5cc30d009483a575cd96c5%2F14.png?alt=media" alt=""><figcaption></figcaption></figure>
2. Design the module UI:
   1. Insert a **container** into the module.
   2. Add two **text** components and an **image** component to the container.
   3. Adjust their properties, such as the layout, height, and style.
3. Bind the components' value to the module inputs. For example, the **Image source** of the image is bound to input parameter `imageUrl.value`.

   <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-c18498c90a9b8df09af57ac886396a1519704991%2F15.png?alt=media" alt=""><figcaption></figcaption></figure>
4. Insert the newly built module into an external app or module, and you can pass in values to configure its properties.

   <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-a08665420a439d40ebb22958fd727930372822bb%2F16.png?alt=media" alt=""><figcaption></figcaption></figure>
5. Reuse the module multiple times by passing different input values.

   <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-05e9f72fdf4d1f73fd84be95e23000fe44ec2251%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Input Test

To quickly test the effectiveness of input parameters during editing a module, you can use the **Input Test** function.In the **module editor**, select the whole module to conduct tests with simulated input data in the **Properties** panel. In the example previously mentioned, you can set the test values for the three module inputs: `title`, `imageUrl`, and `count`, as shown below:

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-1b7d26b75ae123b625817bc735a1db311e2f2829%2F17.png?alt=media" alt=""><figcaption></figcaption></figure>

### Output

Module outputs are the data exposed to an app or other modules. You can inspect the outputs of a module in the data browser and access them via JavaScript code in `{{ }}`.The following example shows the outputs in a user-filtering module.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-801f75a7e7d3bdd11e54e185730fe365c465a475%2F18.png?alt=media" alt=""><figcaption></figcaption></figure>

Then you can check out and reference the outputs of a module in apps or other modules using it.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-d915b36a825a76968a470b9d5af3a61af77db8e3%2F19.png?alt=media" alt=""><figcaption></figcaption></figure>

### Method

#### Add a new method

In the **Settings** tab, click **+** **Add** to create a new module method. Click the method to rename it and select an action. In the following example, the method `clearAll` is designed to clear the content in both input boxes. To achieve this, select **Run JavaScript** as the action, and write JS code to call the `clearValue` method of both two input components.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-01feb567b75d05fbed971b8923f4d9962cebe48c%2F20.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
When creating a method for a module, you cannot create input parameters for the method and can only reference parameters within the scope of the current module.
{% endhint %}

#### Call a method

When using modules, you can call a module method in two ways:

* In event handlers, select **Action** > **Control component**, and then select the **component** and **method**.

  <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-2103744eff0855a0fa54e9cd6517d5638b651346%2F21.png?alt=media" alt=""><figcaption></figcaption></figure>
* Use dot notation in JavaScript queries. For example, `module1.clearAll()` calls the method `clearAll()` of `module1`.

#### Method Test

You can simulate testing method calling in the **Method Test** function.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-3a0c2503d669857b79cd8bfd12ab2174fc2dccc8%2F22.gif?alt=media" alt=""><figcaption></figcaption></figure>

### Event

Events are used to transfer signals from a module to external apps, such as defining `orderPlaced` `OrderModified` events for an order management module. You can add and fire events within a module, and deal with them using [event handlers](/build-apps/event-handlers) externally.

#### Add a new event

In the **Settings** tab, click **+** **Add** to create a new module event. Click the event to set its name.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-dc001d9c55e738c7650a6922f47f4c31cc848c35%2F23.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Trigger an event

In the following example, the event `contentChange` is triggered when the content in any input box changes. You can trigger it in two ways:

* In **Event handlers** of both input components, click **+ Add**, select **Change** as the component event and **Trigger module event** as the action, and finally select the module event `contentChange`.

  <figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-d5c0a117f1c98da8e0ae61bd74299a6fe9f1b1c2%2F24.png?alt=media" alt=""><figcaption></figcaption></figure>
* Use dot notation in JavaScript queries: `contentChange.trigger()`.

#### Event handlers

When an app uses a module, you can configure how the current app reacts to the module's events. For example, in **Event handlers** of `module1`, click **+ Add**, and select the module event `contentChange`and the action **Show notification**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-ed24c98c01f4eee9e2d74c1a43cc834eb9f820be%2F25.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Event Test

The following example conducts event tests in the **Event Test** section.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-e88c7ff0eeaef8e132b8bff92346e458e3add66a%2F26.gif?alt=media" alt=""><figcaption></figcaption></figure>

## Permissions

End users are not automatically granted permissions to view modules in apps or other modules they have viewing permissions with, because of that, you have to grant permission on modules as you do with apps. For more information, see [Permissions for resources](/workspace-management/permissions-for-resources).

## Releases and versions

PocketBlocks stores the history versions of your modules for your references. Click **Preview > Publish** at the top right. The release management of a module is identical to that of an app. For detailed information, see [Version and release management](/build-apps/version-and-release-management#release-management).

{% hint style="info" %}
For an unpublished module, the apps and modules use its latest version; while for a published one, you need to publish it again to sync your latest changes.
{% endhint %}


# Design app UI


# Style, theme, and usability

Good user interface (UI) improves user experience (UX) and increases user involvement. You can customize the style of each component in PocketBlocks and use the theme feature to design the interface on a per-app or workspace basis. Features such as icon configuration and hint messages make the app interaction more user-friendly.

## Component styles

You can modify the style of all components in the **Properties** tab.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-095f63646d2118a8934010d418827e4d471156f3%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Click the color picker to select a color or write CSS color code in the text box.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-133ea217cef313f7f6d24934730112a8f5ec28bd%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

You can also write JavaScript in the text box to conditionally control the style setting of the component.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-1ec9733fb8a81b9d26fa3f025d8de7acc6bfb4df%2F03.gif?alt=media" alt=""><figcaption></figcaption></figure>

## Themes

The theme feature helps you quickly set the styles of all your apps within a workspace, such as the primary color of the apps and the default background color of containers.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-fdbf2b797c2a87b84e21874bb49cf9538c471142%2F04.gif?alt=media" alt=""><figcaption></figcaption></figure>

### Create a theme

Workspace admins have access to theme settings. On PocketBlocks homepage, go to **Settings** > **Themes**, and click **+ Create theme**. Enter the theme name, and select one of the preset default themes as the starting point.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-fbaba1b6547c6be681b428073443688804009749%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

Preview the real-time theme effect on the right.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-5c584f13a0ce9e7982f3dc20b67f95f28318b919%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>

### Apply a theme

In the app editor, switch the theme by clicking ⚙️ on the left side-bar. Select a theme from **Theme setting**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-d58ad1700cfb9d526b5b16305498cb1a714b8924%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>

You can also set the default theme for all your apps within a workspace in **Settings** > **Themes** on PocketBlocks homepage.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-4f02c0cb4285aea794e6b3abf6eb0d9c87fd45f7%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>

### Switching themes dynamically

You can access the global variable `theme` and call the method `theme.switchTo()` to allow the end users to switch the theme of the apps on their side using JavaScript.The global variable `theme` has three fields. You can view them in the data browser.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-6994426cab6c2d05b795c926cd65bdf1cf0addd7%2F09.png?alt=media" alt=""><figcaption></figcaption></figure>

* `id` and `name` are strings, indicating the ID and name of the current theme. When their values are empty, then the default theme is applied.
* `allThemes` is an array, including all information of available themes in the current workspace.

`theme.switchTo()` method switches the theme at the end user's side, and requires only a theme ID. When the passed value is an empty string `""`, then the default theme is applied.Once the end user switches the theme, it will be saved to the user browser's local storage. And this theme will override the default theme and apply to all apps that are used in the same browser.

#### Demo

Combining Option lists and Events, end users can switch the theme within the app.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-b4c4757e07444b87845ab0722869c81a3f0cf3e8%2F10.gif?alt=media" alt=""><figcaption></figcaption></figure>

Follow the steps below to include this function in your app.

1. Drag and drop a **Select** component onto your canvas. Set the data value as follows.

<pre class="language-Plain"><code class="lang-Plain"><strong>{{[{ id: "", name: "Default" }, ...theme.allThemes]}}
</strong></code></pre>

2. Set the labels and values as `{{item.name}}` and `{{item.id}}` respectively. Then, you can view the default theme and all other available themes in the current workspace.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-83842f369b714bbd9bb55db0233ee25a643739a9%2F11.png?alt=media" alt=""><figcaption></figcaption></figure>

3. Insert a **Button** component onto your canvas to switch theme. Add an event to the button, select "Run JavaScript" as the action, and run `theme.switchTo()` method which takes the value of the **Select** component.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-3fe7632126564a4410cc0689f0ea0a7ffe21b69b%2F12.png?alt=media" alt=""><figcaption></figcaption></figure>

## Custom CSS

PocketBlocks provides a custom CSS feature for more flexible and customized UI styling.

### App-level CSS

In the app editor, click ⚙️ on the left side-bar, select **Scripts and style** > **CSS**, and then write CSS code for the current app.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-dc72a3a4d3f0dda0d99980bffd19f4af4c904ef6%2F13.png?alt=media" alt=""><figcaption></figcaption></figure>

For example, insert text component `text1`. Then use `.text1` as the element name and modify its CSS style.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-0ee7475ba2361e1ad91f1788d5c20a126134d79e%2F14.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
It is recommended to modify the component styles in **Properties** > **Style** because the DOM of an adjusted CSS style may change as the system iterates.
{% endhint %}

### Preload CSS

In PocketBlocks, workspace admins can also set pre-loaded CSS styles for all apps within the workspace. Open the **Settings**, and click **Advanced** > **Preload CSS**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-fd0ffc6c9e699076d6f3eeb5270c90a923407164%2F15.png?alt=media" alt=""><figcaption></figcaption></figure>

It is highly recommended to use CSS selectors as follows:

| Class name     | Description               |
| -------------- | ------------------------- |
| top-header     | Top navigation bar        |
| root-container | Root container of the app |

The name of each component functions as the class name. For example, for the `text1` component, you can use `.text1` as its class name and write CSS code for it. And the class names share the same form: `ui-comp-{COMP_TYPE}`—for example, you can use `.ui-comp-select` to define CSS style of all select components. All the components' class names are listed as follows.

```Plain
input
textArea
password
richTextEditor
numberInput
slider
rangeSlider
rating
switch
select
multiSelect
cascader
checkbox
radio
segmentedControl
file
date
dateRange
time
timeRange
button
link
dropdown
toggleButton
text
table
image
progress
progressCircle
fileViewer
divider
qrCode
form
jsonSchemaForm
container
tabbedContainer
modal
listView
navigation
iframe
custom
module
jsonExplorer
jsonEditor
tree
treeSelect
audio
video
drawer
carousel
collapsibleContainer
chart
imageEditor
scanner
```

Avoid using class names that may change with iterations, such as `sc-dkiQaF bfTYCO`.PocketBlocks supports [CSS pre-processor](https://stylis.js.org/), you can use CSS nesting to improve efficiency, for example:

```css
.text1 {
  span {
    color: red;
    font-weight: bold;
  }
}
```

All the custom CSS for apps is saved into the space named `#app-{APP_ID}`, and the CSS for modules is saved into the space named `#module-{MODULE_ID}`.If your preload CSS does not work properly, it might be overridden by the theme or component styles with higher priority. Open the browser **Inspect** to check.

### Demo 1: Line break in table header

To allow line break in table header, insert the following code in **Script and style** > **CSS**.

```css
.table1 {
  th div {
    white-space: pre-wrap;
    word-break: break-word;
    max-height: unset;
  }
}
```

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-cb7fbaacb550e409b629c75c321b118c76296f57%2F16.png?alt=media" alt=""><figcaption></figcaption></figure>

### Demo 2: Custom font family

To use custom font family, you need to define it first and then apply it. Insert the following code in **Script and style** > **CSS** to apply the font "Fredoka One" to all text components using Markdown mode within the app.

```css
@font-face {
  font-family: "Fredoka One";
  font-style: normal;
  font-weight: 400;
  src: url(https://fonts.gstatic.com/s/fredokaone/v13/k3kUo8kEI-tA1RRcTZGmTlHGCaen8wf-.woff2)
    format("woff2");
}

.ui-comp-text .markdown-body {
  font-family: "Fredoka One";
  font-size: 30px;
}
```

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-dd6f08a8a3d19d27d47336bd4804c7bb8d9187d6%2F17.png?alt=media" alt=""><figcaption></figcaption></figure>

## User-friendly interaction

PocketBlocks always lives up to efficiency, security, and easy-to-use design.

### Hide UI components

Set the hidden properties of components when necessary to avoid information overload. For example, when creating a suggestion collection form, you can set the input box as visible or hidden depending on the user's selection. <img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-57cbd086350ba16e972fbf8731547f395b5ade03%2F18.gif?alt=media" alt="" data-size="original">

To achieve this effect, set the hidden property of the component `textArea1` with the code:

```JavaScript
{{Number(radio1.value) === 1 ? 'false' : 'true'}}
```

When the value of the component `radio1` is "1", the value of the hidden property is "false"; otherwise, the value is "true". The component layout is automatically adjusted.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-861b82784ae66bd62c052808e250bfb83796b767%2F19.png?alt=media" alt=""><figcaption></figcaption></figure>

### Icon configuration

Icons are intuitive, and can be alternatives to text in some cases. The proper use of icons gives users a better visual experience, and helps them use the app more easily.

Prefix and suffix icons are available for some components, such as **Button**. Add icons in **Properties** > **Layout**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-5b26ea4b391edaf9ca44367f195c76b9e66c349a%2F20.png?alt=media" alt=""><figcaption></figcaption></figure>

You can select from preset icons or write JS code to insert icons, for example, `{{ "/icon:solid/Users" }}`.

### Placeholder and tooltip

Tips improve app usability–for example, showing the tips for the input helps users better interact with the app.

* Placeholder: It displays in the empty input field to prompt the user what to type.
* Tooltip: It adds an underline to the label. Users can see the tooltip via a mouse hover.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-78b458697f1761bf9b77b95ccf921d3c75dce4e2%2F21.png?alt=media" alt=""><figcaption></figcaption></figure>

### Notifications

Notifications are messages directly sent to your users to remind them of the status of their operations, confirm their success, or help them to proceed.

#### Global notifications

Global notifications for certain user interactions give users timely feedback. PocketBlocks offers four types of global notificaitons: **Information**, **Success**, **Warning** and **Error**.

You can set global notifications in three ways:

1. Set in **Event handlers** > **Action** > **Show notification**. See [Show notification](/build-apps/event-handlers#show-notification) (Event handlers).
2. Set in **JavaScript queries** with [built-in functions](/build-apps/write-javascript/built-in-javascript-functions).
3. Set in **Notification** tab in query settings. See [Notification tab](https://github.com/internoapp/pocketblocks/blob/main/docs/en/queries/query-basics.md#notification-tab-and-advanced-tab).

### Loading effect

When a query takes time to run, you can set the loading effect to inform your users that the query is running and avoid them from performing frequent operations.

For example, the loading effect of the Submit button is `{{form1SubmitToHrmsEn1.isFetching}}`. Clicking the button triggers query `form1SubmitToHrmsEn1` to run, and during this process, the button is displayed with the loading effect.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-0fd77d853092b1307dc855b9c4e2c69f7435d0e4%2F22.gif?alt=media" alt=""><figcaption></figcaption></figure>

#### Confirmation modal

You can set a confirmation modal for a double check for your users when they perform operations such as adding, modifying or deleting data. In the **Advanced** tab of the query, toggle **Show a confirmation modal before running**, and enter a confirmation message.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-398d349be17679cde526665e1f0e5b8714ea29a3%2F23.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Form design

Forms are frequently used to collect information. For more details on building easy-to-follow and productive forms, see [Design an efficient and user-friendly form](/build-apps/design-app-ui/design-an-efficient-and-user-friendly-form).


# Design an efficient and user-friendly form

### Select proper input components

The UX design of input components in a form is crucial to the form's efficiency. Properly chosen components can save users effort and lead to better results. PocketBlocks offers a variety of input components, including text input, number input, option list, and radio buttons, each of which works for different scenarios.

For example, when the input is generated from data, use the option list to let users quickly fill in the input.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-00844451b6ada7d2539c99615e23cc37d202dcf5%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

Other input components, such as radio, are really helpful when the users need to directly choose between two options, for example, to indicate whether they would like to sign up for a particular activity, like a conference.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-caf1188a9a71ab6af6ddf60fe806bef97ffe36ea%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

Number input is also a commonly used component type—for example, in an order management system.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-48f444d611c61dfa62461e1ce07ff5e712f46eab%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

### Keep layout clear and consistent

Keep all input field lengths the same to make the form visually neat, and put all input fields into a single column to achieve better readability.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-9c7555f95cf155b216c28980164c79dbee6b2ced%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

### Group content with PocketBlocks divider

Use the PocketBlocks **Divider** component to group relevant input fields to help users process information in an organized way.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-2111ade1e2b8fb1ccf17f1ff3e6ab44fd66f3d90%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

### Add user feedback

Form component is quite often used for CRUD operations, which sometimes can be risky due to human errors. To avoid harmful CRUD operations, you can add a confirmation modal before the users submit the form.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-cc581455b4c27367316216f92fa18bd939409dcc%2F06.gif?alt=media" alt=""><figcaption></figcaption></figure>

Similarly, a notification after users' submission gives users timely feedback. You can add a global notication to the Submit button. In PocketBlocks, you can add global notifications in three ways. See [global notification](/build-apps/design-app-ui/style-theme-and-usability#global-notifications) for details.

### Clear input fields on submission

Clearing input fields in a form upon submission helps users proceed with the subsequent submissions. You can set in **Properties** tab, and toggle **Reset after successful submit**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-1c7f180a08c73d224e04050f2d745bcbc7fe3675%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>

However, sometimes it is better to leave the form uncleared—for example, when much of the values stay the same in subsequent submissions, or when the user continuously edits data. In such cases, you can insert a button with an event handler to clear each input on click.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-70e2601335fab83219b4eb9dcfbf774406c04683%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>


# Navigation

**Navigation** aggregates your apps onto the left sidebar and guides you to quickly find the needed app.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-f10c70bd1b26154ac6524d025d71b885e946809d%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

On PocketBlocks homepage, click **New** and select **Navigation** to create a navigation page.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-73b80f4764e27c182e140d49b2f35f66a7150608%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

## Menu items

In the **Navigation** editor, click **+ New** to add menu items.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-873566feff0adf4a85517dd86f7d39637efa6f2b%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

Select a menu item, choose the app to navigate to, and change the label and icon if needed. The app is displayed on the canvas in real time.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-459d698c090dc931e1f0d9d97b414ad4f90e4878%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

### Add submenu items

To add submenu items, click `···` > **Add submenu item**, or drag `⋮⋮` to make one menu item subordinated to another.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-e18eba95f41950f9ea204a329ce1e1d728b25f7c%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-e293c845f90684a086320474674fd429e9f9ba09%2F06.gif?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
A parent menu item can only expand or fold the submenu items. You cannot link an app to it.

When you delete a parent menu item, all submenu items under it are deleted at the same time.
{% endhint %}

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-b8f76f31bb08ac3e7589c5d4463c4b6b8c2cd129%2F07.png?alt=media" alt=""><figcaption></figcaption></figure>

### Add URL parameters

Add URL query parameters or hash parameters to a menu item with `key` and `value`.![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-884d21193c5894881ade8604d4c672d6bd803a1d%2F08.png?alt=media)

Then click the menu item on the canvas, and the parameters are appended to the URL of the app to be opened. You can check in **Globals** tab in the left pane.![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-6538e9a9c4ab4f2c62b40108ed99eedf9687ce0f%2F09.png?alt=media)

{% hint style="info" %}
To reference the url parameters, use `{{url.query.key1}}` or `{{url.hash.key1}}` in your app.
{% endhint %}

For more information of URL parameters, see Go to app.

### Visability of menu items

By default, a menu item is hidden for users without app permission. When you toggle this option off, the users can see the menu item but can not view the app it references to.![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-d4b44db77c0a6943532e8581d7fce16b9daee772%2F10.png?alt=media)

## Permissions

The permissions for navigations are the same as those for modules and apps. See Permissions for resources.


# Keyboard shortcuts

## Built-in keyboard shortcuts

Keyboard shortcuts are a powerful tool that can greatly improve productivity and efficiency when working on a computer. With the ability to assign custom keystrokes to frequently used commands, tasks can be completed quickly and with minimal effort. This is particularly useful for individuals who rely heavily on keyboard input, such as programmers, writers, or designers.

Keyboard shortcuts have been around for decades, and most software applications come with a set of default shortcuts. PocketBlocks offers built-in keyboard shortcuts to help you work on the interface faster and more efficiently with improved controlling precision.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-aff01be01dd9b19dcef2a9f126cfad3ccdb94cb0%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

### Global

Global keyboard shortcuts across PocketBlocks interfaces.

| Shortcut | Description               |
| -------- | ------------------------- |
| `?`      | Toggle keyboard shortcuts |

### App editor

Keyboard shortcuts in the [App editor](#app-editor).

| Shortcut      | Description        |
| ------------- | ------------------ |
| `⌘` + `B`     | Toggle left pane   |
| `⌘` + `J`     | Toggle bottom pane |
| `⌘` + `U`     | Toggle right pane  |
| `⌘` + `.`     | Toggle all panes   |
| `⌘` + ⇧ + `P` | Preview            |
| `⌘` + `Z`     | Undo               |
| `⌘` + ⇧ + `Z` | Redo               |
| `⌘`           | Show grid          |

### Component

Keyboard shortcuts to control components.

| Shortcut              | Description     |
| --------------------- | --------------- |
| `⌘` + Click           | Select multiple |
| `⌘` + `A`             | Select all      |
| `⌘` + `C`             | Copy            |
| `⌘` + `X`             | Cut             |
| `⌘` + `V`             | Paste           |
| `←` `↑` `→` `↓`       | Move            |
| `⌘` + `←` `↑` `→` `↓` | Resize          |
| `DEL`/`Backspace`     | Delete          |
| `ESC`                 | Deselect        |

### Query editor

Keyboard shortcuts in the Query editor.

| Shortcut  | Description       |
| --------- | ----------------- |
| `⌘` + `↵` | Run current query |

### Text editor

Keyboard shortcuts in the Text editor.

| Shortcut    | Description       |
| ----------- | ----------------- |
| `⌘` + `L`   | Format            |
| `⌘` + Click | Open in left pane |

## Custom keyboard shortcuts

You can define custom keyboard shortcuts at app-level. Go to ⚙️ on the left side-bar > **App settings** > **Custom shortcuts**. Click **+ Add** to add new shortcuts for specific actions. Then, you can click a custom shortcut to modify it or click the three dots `···` to delete it.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-f2906d668e434e4f975cb879c189b31821f10859%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
PocketBlocks keyboard shortcuts are better set to avoid conflicts with the browser's keyboard shortcuts, in case they can not be successfully triggered.
{% endhint %}


# Version and release management

Version and release management aims at providing a stable live version for end users and allows you to build and test your app safely.

By default, end users interact with the latest version of your app. After drafting and modifying your ideas, you can preview and compare with different history versions, and finally publish the version that meets all your needs. The newly published version now becomes live, and all your future updates will not affect the live version until you publish again.

## History versions

PocketBlocks automatically stores all your history changes during the construction of an app, such as the addition or deletion of the components, adjustment of the property of the components, rearrangement of the layout, and update of a custom function. You can use it to refer to your earlier ideas or revert to a previous version.

App history versions are only accessible to admins.

### View a history version

You can view any version of your previous drafts. Click **Preview** **>** **History**.

![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-4bba5ec95f77fc18a982b36cde3c96be49f3f954%2F01.png?alt=media)

### Restore a history version

You can restore your current draft to a history version.

1. Select the target version from the history version list
2. Click **Restore this version** on the topbar

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-56ca20f7070e2675a243edd6be1bf5f8032f10a4%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

## Release management

Apps are usually upgraded on a regular basis to include new features, improve business processes and correct failures. However, the development of a new version of an app takes time and you need to ensure that user experience is not affected during this progress.

By default, end users interact with the latest version of your app. Once you finalize the sketch for a newer version of your app, you can proceed to publish it. Click **Preview > Publish**.

![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-3208c41bf68d324b05503052ef5e1567a81cec91%2F03.png?alt=media)

Now the newly released version becomes live for all end users, and all your future updates will not affect the live version until you publish again.


# Develop UI component plugins

With PocketBLocks plugins, you can develop customized components that are consistent with native components for your specific scenarios.

## Initialization

Execute the following commands:

```bash
# Project initiation
yarn create pocketblocks-plugin my-plugin

# Go to the project root
cd my-plugin

# Start the development environment
yarn start
```

## Component development environment

After executing `yarn start`, the browser is automatically opened and you enter the component development environment.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-2ea7498f47d82d0af5acb15312197588e7ff4dbd%2F01.jpeg?alt=media" alt="Screenshot of component development environment"><figcaption></figcaption></figure>

## Plugin configurations

In `openblocks` field in `package.json` file, you need to define the component properties. For example, the following is the explanation of several fields:

* `comps` defines UI components contained in the plugin. For each component, the key name of the object is the unique identity, and the value is metadata.
* `comps[someCompKey].name` defines the component name shown in the **Insert** tab.
* `comps[someCompKey].icon` defines the component icon shown on the canvas. Use a relative path to where `package.json` file is located.
* `comps[someCompKey].layoutInfo` defines the component layout:
  * w: width of the component. Counted by the number of grid cells (range: 1 - 24).
  * h: height of the component. Counted by the number of grid cells (range: >= 1).

```bash
  "openblocks": {
    "description": "",
    "comps": {
      "hello_world": {
        "name": "Hello World",
        "icon": "./icons/hello_world.png",
        "layoutInfo": {
          "w": 12,
          "h": 5
        }
      },
      "counter": {
        "name": "Counter",
        "icon": "./icons/hello_world.png"
      }
    }
  }
```

## Export components

To export all the components, use `src/index.ts`, for example:

```bash
import HelloWorldComp from "./HelloWorldComp";

export default {
  hello_world: HelloWorldComp,
};
```

The default exported object `key` needs to be consistent with the `key` configured in `comps` in `package.json` file.

## Publish plugins

When you finish developing and testing the plugin, you can publish it into the npm registry. Login in to the npm registry locally, and then execute the following command:

```
yarn build --publish
```

If you do not specify the parameter `--publish`, the `tar` file will be saved in the root folder.

## Import plugins

In the PocketBLocks app, click **Insert** > **Extensions** > **Add npm plugin** in the right pane. <img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-61d836518578324db0c3851ffd1eb66a5d6bce90%2F02.png?alt=media" alt="" data-size="original">

Input your npm package's URL or name, and then you can use your customized components.

```bash
my-plugin

# or

https://www.npmjs.com/package/my-plugin
```

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-bbad4d457ac4be913d733ae7920f82ef9458eeb4%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

## Code demo

For code demo, refer to PocketBlocks [Github](https://github.com/pedrozadotdev/pocketblocks/tree/main/client/packages/openblocks-plugin-demo).


# Authentication

PocketBlocks provides a huge list of authentication options. If you can use it in [Pocketbase](https://pocketbase.io/), you can use it in PocketBlocks.

## Enable Authentication Options

By default authentication with username and email is enable.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-9e4d38488bc50ad64758217c9d67005645d9aecb%2F08.png?alt=media" alt=""><figcaption></figcaption></figure>

To allow users to authenticate with **OAuth providers**, go to the Pocketbase Admin Panel, **Settings** in the side menu, select **Auth providers**, and configure some of the options available.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-6da00dab025bc7869367597b6c4bc4933c29e85a%2F14.png?alt=media" alt=""><figcaption></figcaption></figure>

## Signup

By default, anyone can sign up. To disable the signup page (and feature), create a rule with restrictions.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-2b92d8eac3ceb7019460b61a2309d689b95392cf%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

## Customization

You can customize some aspects of the authentication page. Go to **PocketBlocks Settings** Page then go to **Authentication**:

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-e8e94a70d408ee664fbd3caef1196f6c5cd2a4bb%2F03.png?alt=media" alt=""><figcaption></figcaption></figure>

You can change the username input label and apply a mask by selecting the **Local** login type option:

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-6d1bdc1416a20648eb2e129c55298cd63e6ed340%2F04.png?alt=media" alt=""><figcaption></figcaption></figure>

You also can change the name of an OAuth provider and its icon by selecting the respective login type option:

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-bbeb42f8dd816aa9028a05adeb8698e55d1b2031%2F05.png?alt=media" alt=""><figcaption></figcaption></figure>

## Email Features

To enable password recovery and email verification/change, you need to configure a **SMTP Server** in PocketBase Admin Panel:

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-74a672cf5c5a92a2653fc3176b31e0f6c822621b%2F06.png?alt=media" alt=""><figcaption></figcaption></figure>


# Members and groups

In PocketBlocks, you can organize the members of your workspace using different groups, and assign roles to groups to manage [permissions for resources](/workspace-management/permissions-for-resources). You can find members and groups settings in **users** and **groups** on Pocketbase Admin Panel.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-91b1208a103d401a25199c49541efef6db43c1e6%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

## Manage workspace members

### Workspace roles and permissions

Users can be **Admins** or **Members**. To be an **Admin** the user needs to be a **Pocketbase Admin**, if not, it will be a **member**.

| Role   | Workspace and group level permissions                                                                                                                                                                                                            |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Admin  | <p>Workspace</p><ul><li>Modify workspace information (name, logo, etc.)</li><li>Manage workspace members</li><li>View workspace members</li></ul><p>Groups</p><ul><li>Create groups</li><li>Delete groups</li><li>Manage group members</li></ul> |
| Member | None                                                                                                                                                                                                                                             |

## Manage groups

Group-based management helps to organize members from different functional departments in your workspace. You can create groups in **groups** Pocketbase collection.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-5276e9a2c308b8d697501f78e232b252d43a8a29%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

### Group roles and permissions

The permissions are listed in the table below.

| Role   | Permissions                                                                                                                                                         |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Admin  | <ul><li>Change group name</li><li>Delete groups</li><li>Manage group members</li><li>View group members</li><li>Manage group apps</li><li>View group apps</li></ul> |
| Member | View group apps                                                                                                                                                     |


# Permissions for resources

Manage permissions for apps, modules, navigations and folders in your workspace.

Permissions determine the actions users can take on resources, including apps, modules, navigations, folders.

Only workspace admins are allowed to create resources.

## Apps, modules, **navigations**

The permissions for these three resources are the same.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-96ba885ae39e93798709bca30cd6c7fb4d926a03%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

### Share and set roles

**Admins** can add members and assign a **viewer role** to them. When editing a web app, a module or a navigation, click **Share** at the top right, then click **Add members**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-79fe2a74a2599dc6424121ad4c3d71f1d50753ed%2F02.png?alt=media" alt=""><figcaption></figcaption></figure>

Choose members and groups from the list.

![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-ccb9d853104f255bb5caa950b1ce99b0ccb0653e%2F03.png?alt=media)

### Make public

If you want to make an app or a module or a navigation public to all users (including anonymous users), you can toggle on **Make the app public** in **Share** settings.

![](https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-b53d50a2b57d79e309e09c9f47a29ad191f46323%2F04.png?alt=media)

## Folder

Folders help you sort out the apps, modules, and navigations in the workspace. Only workspace **admins** have the following permissions for folders:

* Create
* Rename
* Delete
* Move the apps, modules and navigations into or out of folders


# Custom branding

PocketBlocks provides a white-labeling feature that allows you to customize your workspace's **branding**, including logo, favicon, brand name and color. You can easily configure branding to match your company's branding and benefit from consistent experiences with your company's existing internal tools.

## Branding settings

Only **Admins** have permission to customize branding. Navigate to **PocketBlocks Settings** and go to **Branding**.

<figure><img src="https://3954266794-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdzgVkwpxTMW0dI30zZ8Y%2Fuploads%2Fgit-blob-315d54523380208c20b29c1ec1f5b16dc64495ab%2F01.png?alt=media" alt=""><figcaption></figcaption></figure>

As you change the data, the preview on the side updates in real time.

{% hint style="info" %}
This customization only applies to non-administrators, so administrators continue to view the default branding(PocketBlocks).
{% endhint %}


# Where are the Data Sources/Query Library?

PocketBlocks integrates Openblocks and PocketBase, or at least the client's part. As this project aims to create as much flexibility as possible between those two software, we opted not to port the **data source/query library** features as we have access to the [Pocketbase SDK](https://pocketbase.io/docs/client-side-sdks/) through **window\.pb**. We also can use the [extend features](https://pocketbase.io/docs/js-overview/) of Pocketbase to integrate with data sources using something like [n8n](https://n8n.io/) or [Zarpier](https://zapier.com/).

{% hint style="info" %}
We also provide a [QueryClient instance](https://tanstack.com/query/v5/docs/reference/QueryClient) for caching purposes. You can access it with **window\.qc**. It uses sessionStorage with a staleTime of 5 minutes.
{% endhint %}


# Embedding Apps

It is also possible to embed PocketBlocks Apps on any HTML Page with simple Scripts, using the [PocketBlocks SDK](https://github.com/pedrozadotdev/pocketblocks/tree/main/client/packages/openblocks-sdk) through **window.$pbl**. This enables you to embed PocketBlocks Apps even without deep knowledge of React or Web Development.

## How to

To do it, all installations of PocketBlocks bring an **embedded.html** file in **pb\_public** folder with a code example.

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>PocketBlocks Embedded</title>
    <script type="module" crossorigin src="/js/proxy.js"></script>
    <style>
      .demo-title {
        text-align: center;
      }
      .demo {
        overflow: auto;
        padding: 10px;
      }
      .ops {
        padding: 10px;
      }
      .ops button {
        margin-right: 10px;
      }
    </style>
    <script type="module" crossorigin src="/js/embedded.js"></script>
    <link rel="modulepreload" crossorigin href="/js/<HASH>.js" />
    <link rel="stylesheet" href="/assets/index-<HASH>.css" />
  </head>
  <body>
    <h1 class="demo-title">PocketBlocks Embedded</h1>
    <div id="app" class="demo"></div>

    <script>
      window.onload = async function () {
        const url = new URL(location.href);
        const appId = url.searchParams.get("appId");
        const baseUrl = url.searchParams.get("baseUrl") || location.origin;
        if (!appId) {
          return;
        }
        const instance = await $pbl.bootstrapAppAt(
          appId,
          document.querySelector("#app"),
          {
            baseUrl,
            moduleInputs: { userName: "Lucy" },
          }
        );

        instance?.on("moduleOutputChange", (output) => {
          console.info("output change:", output);
        });

        instance?.on("moduleEventTriggered", (eventName) => {
          console.info("event triggered:", eventName);
        });

        document.querySelector("#app-ops")?.addEventListener("click", (e) => {
          const target = e.target;
          const key = target.dataset.key;
          if (key === "setModuleInputs") {
            instance?.setModuleInputs({
              userName: "Tom",
            });
          }
          if (key === "invokeMethod") {
            instance?.invokeMethod("setSlider");
          }
        });
      };
    </script>
  </body>
</html>
```

You can test it accessing your local installation at `http://<host>/embedded.html?appId=<appSlug>`

{% hint style="warning" %}
Only **apps** can be embedded in pages. Do not use **navigations** or **modules**.
{% endhint %}

{% hint style="info" %}
Do not copy the code above. Always access your **embedded.html** to get the correct code as `<HASH>` changes with updates.
{% endhint %}


