SWCore
SWCore / Componentes / Conteúdo via JSON

Conteúdo via JSON Componentes

Busca uma lista em JSON e monta os cartões na tela sozinho — você escreve um modelo com {{campo}} e ele repete para cada item.

O que é

Serve para mostrar na página uma lista que vem de um endereço (a sua API, um arquivo .json): produtos, vantagens, depoimentos, cidades atendidas. Você escreve um cartão de exemplo dentro de um <template>, marcando com {{campo}} onde entra cada informação, e o SWCore repete esse cartão uma vez para cada item da lista. Também preenche as opções de um <select> com a mesma lista.

Quando a página abre (ou quando a pessoa clica, ou quando o bloco aparece na tela — você escolhe), ele busca o endereço, lê a lista e troca cada {{campo}} pelo valor daquele item. Aceita a lista pura ([ … ]) ou dentro de dados ou data ({ "dados": [ … ] }). Se a lista vier vazia, mostra a mensagem de "vazio"; se a busca falhar, mostra a mensagem de erro. Não precisa escrever JavaScript.

Quando usar

  • Lista que muda sem mexer no HTML: vantagens, planos, unidades da loja, equipe — você atualiza o JSON e a página acompanha.
  • <select> de categorias/cidades que vem do banco: sw-content-select.
  • Carregar só quando precisar: sw-content-trigger="visible" (ao aparecer na tela) ou "click" (num botão "Ver mais").
  • Se o seu servidor devolve HTML pronto em vez de JSON, o componente certo é o AJAX declarativo.

Comece aqui

  1. 1

    Coloque o SWCore na página (CSS no <head>, JS no fim do <body>).

    <link rel="stylesheet" href="https://swcore.sanweb.com.br/dist/2.1.0/swcore.min.css">
    
    <!-- fim do <body> -->
    <script src="https://swcore.sanweb.com.br/dist/2.1.0/swcore.min.js"></script>
  2. 2

    Tenha um endereço que devolva uma lista em JSON. Este é o arquivo usado nos exemplos desta página:

    [
      { "id": "1", "titulo": "Entrega em 24h", "resumo": "Pedidos aprovados até as 15h saem no mesmo dia.", "autor": "Logística" },
      { "id": "2", "titulo": "Troca sem burocracia", "resumo": "Sete dias para trocar, sem precisar justificar.", "autor": "Atendimento" }
    ]
  3. 3

    Escreva o bloco com sw-content="endereço" e, dentro, um <template> com o cartão de exemplo usando {{campo}}.

    <div sw-content="/api/vantagens.json">
      <template>
        <div class="bg-sur bd p-m r-m mb-3">
          <strong>{{titulo}}</strong>
          <div class="t-p op-8">{{resumo}}</div>
        </div>
      </template>
    </div>

Todas as variações

Cada quadro abaixo é o componente de verdade, rodando. O código embaixo é exatamente o que está no quadro: copie e cole.

1. Onde os dados aparecem

O mesmo arquivo JSON, desenhado de jeitos diferentes. Tudo que está dentro do <template> é repetido para cada item.

Lista de cartões — {{campo}} no texto
<div sw-content="../../assets/demo-content.json">
  <template>
    <div class="bg-sur bd p-m r-m mb-3">
      <strong>{{titulo}}</strong>
      <div class="t-p op-8">{{resumo}}</div>
    </div>
  </template>
</div>
{{campo}} também funciona dentro de atributos (link, imagem, título)
<ul sw-content="../../assets/demo-content.json">
  <template>
    <li><a href="#vantagem-{{id}}" title="{{resumo}}" class="Tsw-link">{{titulo}}</a> — <span class="op-7">{{autor}}</span></li>
  </template>
</ul>
sw-content-tmpl — o modelo mora fora do bloco (e pode ser reaproveitado)
<template id="tmpl-vantagem-demo">
  <div class="flx alc gap-3 mb-3"><i class="swi-check t-pri"></i> {{titulo}}</div>
</template>
<div sw-content="../../assets/demo-content.json" sw-content-tmpl="#tmpl-vantagem-demo"></div>

2. Preenchendo um <select>

Num <select> não precisa de <template>: diga qual campo vira o texto da opção (sw-content-select) e, se quiser, qual vira o valor enviado no formulário (sw-content-value).

Texto = titulo, valor = id <select sw-inp sw-content="../../assets/demo-content.json" sw-content-select="titulo" sw-content-value="id" aria-label="Vantagem"></select>
Sem sw-content-value: o valor é o próprio texto <select sw-inp sw-content="../../assets/demo-content.json" sw-content-select="autor" aria-label="Setor"></select>

3. Quando buscar

Por padrão ele busca assim que a página abre. Dá para esperar a pessoa pedir ou o bloco aparecer na tela.

sw-content-trigger="click" — busca ao clicar no botão indicado em sw-content-btn
<button type="button" sw-btn="out p" id="ct-demo-btn">Ver vantagens</button>
<div sw-content="../../assets/demo-content.json" sw-content-trigger="click" sw-content-btn="#ct-demo-btn" class="mt-3">
  <template>
    <div class="flx alc gap-3 mb-3"><i class="swi-check t-suc"></i> {{titulo}}</div>
  </template>
</div>
sw-content-trigger="visible" — busca quando o bloco entra na tela
<div sw-content="../../assets/demo-content.json" sw-content-trigger="visible">
  <template>
    <div class="flx alc gap-3 mb-3"><i class="swi-star t-pri"></i> {{titulo}} <span class="op-7">({{autor}})</span></div>
  </template>
</div>

4. Formatos de resposta e mensagens

Nestes quadros a "resposta da API" está escrita direto no endereço (data:application/json,…) só para simular cada caso sem internet. No seu site, é o endereço da sua API.

Lista dentro de "dados" (ou "data") <div sw-content='data:application/json,{"dados":[{"nome":"Ana","cargo":"Designer"},{"nome":"Bruno","cargo":"Programador"}]}'> <template> <div class="mb-3"><strong>{{nome}}</strong> — {{cargo}}</div> </template> </div>
sw-content-empty — lista vazia <div sw-content="data:application/json,[]" sw-content-empty="Nenhum pedido por aqui ainda."> <template><div>{{numero}}</div></template> </div>
sw-content-err — quando a busca falha <div sw-content="data:application/json,resposta-quebrada" sw-content-err="Não foi possível carregar agora. Tente de novo."> <template><div>{{titulo}}</div></template> </div>

Tabela de opções

PalavraO que fazExemplo
No bloco
sw-contentEndereço que devolve a lista em JSON. Obrigatório.sw-content="/api/produtos.json"
sw-content-tmplOnde está o modelo, quando ele fica fora do bloco (um <template id="…">). Sem ele, usa o <template> de dentro.sw-content-tmpl="#cartao"
sw-content-triggerQuando buscar: load (padrão, ao abrir) · click · visible (ao aparecer na tela).sw-content-trigger="visible"
sw-content-btnCom trigger="click": qual botão dispara a busca. Sem ele, é o primeiro elemento da página com sw-content-load.sw-content-btn="#ver-mais"
sw-content-loadMarca o botão que dispara a busca quando não se usa sw-content-btn.<button sw-content-load>
sw-content-emptyTexto mostrado quando a lista vem vazia. Sem ele, fica em branco.sw-content-empty="Nada por aqui."
sw-content-errTexto mostrado quando a busca falha. Padrão: "Erro ao carregar conteúdo."sw-content-err="Tente mais tarde."
sw-content-paginatePede a lista por páginas: acrescenta ?page=1, ?page=2… no endereço e mostra botões Anterior/Próxima.sw-content-paginate
No <select>
sw-content-selectCampo do item que vira o texto de cada opção.sw-content-select="nome"
sw-content-valueCampo que vira o valor enviado. Sem ele, o valor é o próprio texto.sw-content-value="id"
No modelo
{{campo}}Onde entra o valor daquele campo. Vale no texto e dentro de atributos. Só nome simples (letras, números e _).<h3>{{titulo}}</h3>
Formato da resposta
[ … ]Lista pura.[{"titulo":"A"},{"titulo":"B"}]
{ "dados": [ … ] }Lista dentro de dados (ou data).{"dados":[…]}
pagina / paginasCom sw-content-paginate: página atual e total. Também aceita page/pages e current_page/last_page.{"dados":[…],"pagina":1,"paginas":5}

Receitas prontas — usos reais

Situações que aparecem em quase todo site. Copie a que servir.

Lista de vantagens na página inicial Ao vivo
<div sw-content="/api/vantagens.json" sw-content-empty="Em breve novidades.">
  <template>
    <div class="flx gap-3 mb-4">
      <i class="swi-check t-suc"></i>
      <div><strong>{{titulo}}</strong><div class="t-p op-8">{{resumo}}</div></div>
    </div>
  </template>
</div>
Formulário com cidades vindas do banco Ao vivo
<label for="cidade">Cidade</label>
<select sw-inp id="cidade" name="cidade"
        sw-content="/api/cidades.json"
        sw-content-select="nome"
        sw-content-value="id"></select>
"Ver mais" que só busca quando a pessoa pede Ao vivo
<div sw-content="/api/depoimentos.json" sw-content-trigger="click" sw-content-btn="#ver-mais">
  <template>
    <div class="bg-sur bd p-m r-m mb-3">{{titulo}}</div>
  </template>
</div>
<button type="button" sw-btn="pri p" id="ver-mais">Ver mais depoimentos</button>
Lista paginada (blog, catálogo) Referência
<!-- o SWCore chama /api/posts?page=1, ?page=2… e desenha os botões Anterior/Próxima -->
<div sw-content="/api/posts" sw-content-paginate>
  <template>
    <article class="bd p-m r-m mb-3">
      <h3>{{titulo}}</h3>
      <p>{{resumo}}</p>
    </article>
  </template>
</div>

<!-- a API responde assim: -->
<!-- { "dados": [ … ], "pagina": 1, "paginas": 5 } -->
Usar o dado no seu próprio código (gráfico, cálculo) Referência
<script>
  // recarregar um bloco sw-content (ex.: depois de salvar algo)
  SW.Content.load(document.querySelector('#lista-pedidos'));

  // só ler o JSON, sem desenhar nada
  SW.Content.fetchJSON('/api/vendas.json').then((dados) => montarGrafico(dados));

  // saber quando a lista terminou de aparecer
  document.addEventListener('sw:content:loaded', (e) => {
    console.log('chegou', e.detail.dados);
  });
</script>

Eventos

sw:content:loaded
A lista chegou e já está na tela. Dispara no próprio bloco (e sobe até o document). e.detail.dados traz o JSON recebido.

API (JavaScript)

SW.Content.load(elemento)
Busca de novo e redesenha aquele bloco sw-content.
SW.Content.fetchJSON(url, { method, headers, body })
Só busca e devolve o JSON (uma Promise), sem desenhar nada — para usar no seu código.

Precisa de quê

  • swcore.min.css e swcore.min.js.
  • Um endereço que devolva JSON. Se for de outro domínio, ele precisa liberar o acesso (CORS).

Cuidados — erros comuns

  • Classes de grade no próprio bloco (class="l l-3") funcionam: cada item vira filho direto do bloco. A paginação e as mensagens de vazio/erro ocupam a linha inteira da grade.
  • O {{campo}} precisa ter exatamente o nome do campo no JSON (maiúsculas contam). Campo que não existe vira vazio, sem aviso.
  • Campo dentro de campo ({{cliente.nome}}) não funciona: achate o JSON no servidor.
  • Configure sempre sw-content-empty: sem ele, lista vazia vira um espaço em branco e a pessoa acha que está carregando.
  • Não coloque em {{campo}} de um href um valor que o visitante digitou (ele poderia gravar um link perigoso). Dados assim devem ser conferidos no servidor.

O que ele não faz

  • O conteúdo é montado no navegador depois que a página abre: o Google pode não ler essa lista. Conteúdo importante para busca deve vir pronto do servidor.
  • Não formata valores (moeda, data): o JSON já deve trazer o texto como deve aparecer.