Pular para o conteúdo principal

Introdução

Defina campos personalizados para seu conteúdo sem tocar no código.

🎯 O que este módulo faz?

O módulo AttributesSets permite que você use campos personalizados para seu conteúdo (produtos, páginas, formulários, etc.) sem codificá-los diretamente em sua aplicação.

Pense nisso como um construtor de formulários para seus dados - você define quais campos precisa, e o OneEntry cuida do resto.

📖 Explicação Simples

Imagine que você está construindo uma loja online. Cada produto precisa de:

  • Nome (texto).
  • Preço (número).
  • Imagem (foto).
  • Descrição (texto longo).
  • Categoria (dropdown).

Em vez de codificar esses campos em seu aplicativo, você usa Attributes para defini-los no painel de administração do OneEntry. Então você pode:

  • Adicionar novos campos a qualquer momento (sem mudanças de código!).
  • Reutilizar campos em diferentes tipos de conteúdo.
  • Mudar tipos de campo sem precisar redeployar.
  • Gerenciar toda a estrutura de conteúdo em um só lugar.

Exemplo do mundo real:

Sem Attributes (codificado):
- Código: const product = { name, price, image, description }
- Para adicionar o campo "cor" → Mudar o código, redeploy, esperar.

Com Attributes (dinâmico):
- Painel de administração: Adicione o atributo "cor".
- O código inclui automaticamente o novo campo.
- Nenhum deployment necessário!

✨ Conceitos Chave

O que é um Atributo?

Um atributo é um único campo que armazena dados.

Exemplos:

  • Nome do produto (string).
  • Preço do produto (float).
  • Imagem do produto (imagem).
  • Data de publicação (data).

O que é um Conjunto de Atributos?

Um conjunto de atributos é uma coleção de atributos que define uma estrutura.

Exemplo: Conjunto de Atributos do Produto

- name (string)
- price (float)
- description (text)
- images (grupo de imagens)
- category (lista)
- inStock (inteiro)

Por que usar Conjuntos de Atributos?

❌ Sem Attributes✅ Com Attributes
Campos codificadosCampos dinâmicos
Mudanças de código necessáriasEditar no painel de administração
Redeploy necessárioAtualizações ao vivo
Estrutura rígidaEstrutura flexível
Código duplicadoConjuntos reutilizáveis

📋 O que você precisa saber

Três Termos Importantes

TermO que éExemplo
MarkerIdentificador de código único"product_name"
TypeQue tipo de dado armazena"string", "integer", "image"
ValueValor do atributo"Nome do Produto"

Importante sobre Markers:

  • Devem ser únicos
  • Sem espaços permitidos (use _ em vez disso)
  • Não podem começar com um número
  • Use letras minúsculas para consistência

Exemplos:

  • ✅ Bom: product_name, price_usd, main_image
  • ❌ Ruim: product name, 2nd_price, Product Name

Reutilização

Conjuntos de atributos podem ser reutilizados em diferentes entidades:

Conjunto de Atributos "Informações Básicas":
- title (string)
- description (text)
- publish_date (date)

Usado por:
- Postagens de blog
- Artigos de notícias
- Páginas de produtos
- Listagens de eventos

Por que isso importa: Mude uma vez, atualizações em todos os lugares!


📚 Tipos de Dados Disponíveis

Os atributos podem armazenar diferentes tipos de dados. Escolha o tipo certo para cada campo.

Tabela de Referência Rápida

TipoMelhor ParaUso Exemplo
stringTexto curtoNome do produto, email
textTexto longo formatadoPostagem de blog, descrição
textWithHeaderTexto com títuloSeções de artigo
integerNúmeros inteirosQuantidade, idade
realDecimais de alta precisãoDados científicos
floatNúmeros decimaisPreço, avaliação
dateApenas a dataData de nascimento, prazo
dateTimeData + horaInício do evento, publicado em
timeApenas a horaHorário de funcionamento
fileQualquer arquivoPDF, documento
imageImagem únicaAvatar, logo
groupOfImagesMúltiplas imagensGaleria de fotos
radioButtonEscolha únicaTamanho (P/M/G)
listSeleção em dropdownPaís, categoria
entityLink para outro conteúdoProdutos relacionados
timeIntervalIntervalo de datasPeríodo de promoção
jsonDados estruturados personalizadosResposta de API

🔍 Descrições Detalhadas dos Tipos de Dados

Tipos de Texto

Quando usar o que:

  • string - Linha única, menos de 255 caracteres (nome, email, título)
  • text - Múltiplos parágrafos, suporta formatação (artigos, descrições)
  • textWithHeader - Texto que precisa de um título (seções de blog, FAQs)

Tipos de Números

Quando usar o que:

  • integer - Sem decimais necessários (idade, quantidade, visualizações)
  • float - Decimais padrão (preço $19.99, avaliação 4.5)
  • real - Precisão extra necessária (cálculos científicos)

Tipos de Data/Hora

Quando usar o que:

  • date - Apenas o dia (aniversário, prazo)
  • time - Apenas a hora (horário comercial, hora do compromisso)
  • dateTime - Ambos necessários (início do evento, artigo publicado)
  • timeInterval - Período entre datas (duração da venda, datas de férias)

Tipos de Arquivo e Imagem

Quando usar o que:

  • file - Qualquer documento (PDF, DOC, ZIP)
  • image - Uma imagem (foto do produto, avatar)
  • groupOfImages - Múltiplas imagens (galeria, imagens do produto)

Tipos de Seleção

Quando usar o que:

  • radioButton - Escolher apenas UMA opção (Sim/Não, Tamanho P/M/G)
  • list - Dropdown com opções (País, Categoria, Status)

Tipos Avançados

  • entity - Link para outras páginas/produtos (Itens Relacionados, Categorias)
  • json - Armazenar estruturas de dados complexas (respostas de API, configurações)

📖 Exemplos de Tipos de Dados

Abaixo estão exemplos técnicos da estrutura de cada tipo de dado.

Clique para ver todos os exemplos de tipos de dados

Referência de Tipos de Dados

Os tipos de dados podem ser dos seguintes tipos:

  • String: Texto simples, por exemplo, "Olá, mundo!".

Exemplo:

{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"requiredValidator": {
"strict": true
}
},
"localizeInfos": {
"title": "String"
},
"additionalFields": [
{
"type": "integer",
"value": "10",
"marker": "Extra"
}
]
}

  • Text: Texto mais longo, frequentemente formatado, por exemplo, um artigo ou uma carta.

Exemplo:

{
"type": "text",
"value": {},
"marker": "text",
"position": 2,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Text"
},
"additionalFields": []
}

  • Text with Header: Texto com um cabeçalho que pode ser usado para denotar um tópico ou categoria.

Exemplo:

{
"type": "textWithHeader",
"value": {},
"marker": "text_with_header",
"position": 3,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Text With Header"
},
"additionalFields": []
}

  • Integer: Um número inteiro, por exemplo, 5, 100, -2.

Exemplo:

{
"type": "integer",
"value": {},
"marker": "integer",
"position": 4,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Integer"
},
"additionalFields": []
}

  • Real: O mesmo que Float, mas com maior precisão.

Exemplo:

{
"type": "real",
"value": {},
"marker": "real_number",
"position": 5,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Real Number"
},
"additionalFields": []
}

  • Float: Um tipo de dado para números de ponto flutuante que podem ter uma parte decimal, por exemplo, 3.14, 1.5, -0.25.

Exemplo:

{
"type": "float",
"value": {},
"marker": "float",
"position": 6,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Float"
},
"additionalFields": []
}

  • Date and Time: Uma combinação de data e hora, por exemplo, 2023-10-27 10:00:00.

Exemplo:

{
"type": "dateTime",
"value": {},
"marker": "date_time",
"position": 7,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "DateTime"
},
"additionalFields": []
}

  • Date: Uma data, por exemplo, 2023-10-27.

Exemplo:

{
"type": "date",
"value": {},
"marker": "date",
"position": 8,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Date"
},
"additionalFields": []
}

  • Time: Um horário, por exemplo, 10:00:00.

Exemplo:

{
"type": "date",
"value": {},
"marker": "date",
"position": 8,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Date"
},
"additionalFields": []
}

  • File: Qualquer arquivo no seu computador, por exemplo, um documento, imagem, música.

Exemplo:

{
"type": "file",
"value": {},
"marker": "file",
"position": 10,
"listTitles": [],
"validators": {
"checkingFilesValidator": {
"maxUnits": "kb",
"maxValue": "2000",
"minUnits": "kb",
"minValue": 0,
"extensions": []
}
},
"localizeInfos": {
"title": "File"
},
"additionalFields": []
}

  • Image: Uma imagem, por exemplo, uma fotografia, desenho.

Exemplo:

{
"type": "image",
"value": {},
"marker": "image",
"position": 11,
"listTitles": [],
"validators": {
"sizeInPixelsValidator": {
"maxX": "500",
"maxY": "500"
}
},
"localizeInfos": {
"title": "Image"
},
"additionalFields": []
}

  • Group of Images: Uma coleção de imagens, por exemplo, um álbum de fotos.

Exemplo:

{
"type": "groupOfImages",
"value": {},
"marker": "image_group",
"position": 12,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Image Group"
},
"additionalFields": []
}

  • Radio Button: Um botão de seleção do qual apenas uma opção pode ser escolhida.

Exemplo:

{
"type": "radioButton",
"value": {},
"marker": "radio",
"position": 13,
"listTitles": [
{
"title": "A",
"value": "a",
"extended": {
"type": null,
"value": null
},
"position": 1
},
{
"title": "B",
"value": "b",
"extended": {
"type": null,
"value": null
},
"position": 2
}
],
"validators": {},
"localizeInfos": {
"title": "Radio"
},
"additionalFields": []
}

  • List: Uma lista de itens, por exemplo, uma lista de compras.

Exemplo:

{
"type": "list",
"value": {},
"marker": "list",
"position": 14,
"listTitles": [
{
"title": "A",
"value": "a",
"extended": {
"type": null,
"value": null
},
"position": 1
},
{
"title": "B",
"value": "b",
"extended": {
"type": null,
"value": null
},
"position": 2
},
{
"title": "C",
"value": "c",
"extended": {
"type": "string",
"value": "Valor Adicional"
},
"position": 3
}
],
"validators": {},
"localizeInfos": {
"title": "List"
},
"additionalFields": []
}

  • Entity: Uma entidade representando um objeto.

Exemplo:

{
"type": "entity",
"value": {},
"marker": "entity",
"position": 15,
"listTitles": [
{
"title": "Produtos",
"value": {
"id": 1,
"depth": 0,
"parentId": null,
"position": 1,
"selected": true
}
},
{
"title": "Página Normal",
"value": {
"id": 4,
"depth": 0,
"parentId": null,
"position": 2,
"selected": true
}
},
{
"title": "Erro",
"value": {
"id": 2,
"depth": 0,
"parentId": null,
"position": 3,
"selected": true
}
}
],
"validators": {},
"localizeInfos": {
"title": "Entity"
},
"additionalFields": [
{
"type": "string",
"value": "Campo de Teste",
"marker": "test_field"
}
]
}

  • Time interval: Um calendário flexível com uma interface amigável para gerenciar dados de intervalo de tempo.

Exemplo:

{
"time_interval": {
"id": 4,
"type": "timeInterval",
"value": [
// Array de grupos de valores, cada um vinculado a um intervalo específico (via intervalId). Este array é formado quando Receber valores é habilitado no CMS
{
// Registros de tempo específicos aplicáveis às datas especificadas
"values": [
{
// Identificador único do registro
"id": "1dc1787d-acc3-4315-a45d-52166c72e577",
// Intervalo de datas (inclusivo) ao qual este registro se aplica
"dates": ["2025-11-27T00:00:00.000Z", "2025-11-27T00:00:00.000Z"],
// Array de intervalos de tempo no formato [[início, fim], ...]
"times": [
[
// Início do intervalo de tempo (horas e minutos)
{
"hours": 19,
"minutes": 18
},
// Fim do intervalo de tempo
{
"hours": 21,
"minutes": 19
}
]
],
// Reservado (não utilizado na implementação atual)
"intervals": [],
// Exceções — segmentos de tempo excluídos da programação na data especificada
"exceptions": [
{
// Data da exceção
"date": "2025-12-17T17:00:00.000Z",
// Array de segmentos de tempo excluídos
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
// Referência ao intervalo do array `intervals`
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6",
// Flag para recorrência semanal (no dia correspondente da semana)
"inEveryWeek": true
},
{
"id": "cfa187d3-0284-4e0d-8206-7b353cf47110",
"dates": ["2025-12-18T00:00:00.000Z", "2025-12-18T00:00:00.000Z"],
// Array de intervalos de tempo no formato [[início, fim], ...]
"times": [
[
{
"hours": 0,
"minutes": 25
},
{
"hours": 0,
"minutes": 27
}
],
[
{
"hours": 19,
"minutes": 18
},
{
"hours": 21,
"minutes": 19
}
]
],
"intervals": [],
"exceptions": [
{
"date": "2025-12-17T17:00:00.000Z",
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6"
},
{
"id": "474de0f7-595f-49a5-aaa7-65617203ae69",
"dates": ["2025-12-25T00:00:00.000Z", "2025-12-25T00:00:00.000Z"],
// Sem intervalos de tempo
"times": [],
// Regras dinâmicas para expansão da programação
"external": [
{
// Data base para calcular o evento recorrente
"date": "2026-01-15T00:00:00.000Z",
// O evento se repete todo mês neste dia
"inEveryMonth": true
}
],
"intervals": [],
"exceptions": [
{
"date": "2025-12-17T17:00:00.000Z",
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6",
// Flag para recorrência semanal
"inEveryWeek": true,
// Flag para recorrência mensal
"inEveryMonth": true,
// Flag para recorrência anual
"inEveryYears": true
}
],
// Referência ao intervalo do array `intervals`
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6"
},
{
"values": [
{
"id": "2f80dc18-16da-45cb-82c6-e41e1f6ee084",
"dates": ["2025-12-22T00:00:00.000Z", "2025-12-23T00:00:00.000Z"],
"times": [],
"intervals": [],
"exceptions": [],
"intervalId": "918175fd-cc18-4ca5-9bee-c78c61c9415a",
"inEveryWeek": true,
"inEveryMonth": true
}
],
"intervalId": "918175fd-cc18-4ca5-9bee-c78c61c9415a"
}
],
"isPrice": false,
"original": true,
"intervals": [
// Array de templates de intervalo de tempo
{
// Identificador único do template de intervalo
"id": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6",
"range": [
// Intervalo principal de aplicabilidade do intervalo
"2025-11-26T17:00:00.000Z",
"2025-11-26T17:00:00.000Z"
],
// Exceções no nível de intervalo inteiro
"external": [
{
"date": "2025-12-17T17:00:00.000Z",
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
// Intervalos internos (períodos de trabalho/ativos)
"intervals": [
{
"id": "01fea594-9933-47ac-af0a-ec0e0884f618",
// Fim do intervalo de tempo
"end": {
"hours": 21,
"minutes": 19
},
// Início do intervalo de tempo
"start": {
"hours": 19,
"minutes": 18
},
// Duração do bloco repetido (em minutos); null — sem periodicidade
"period": null
},
{
"id": "22ba24af-1fae-4422-8c92-0635b684a306",
"end": {
"hours": 0,
"minutes": 29
},
"start": {
"hours": 0,
"minutes": 25
},
// Periodicidade: os intervalos de tempo se repetem com um passo de 2 minutos
"period": 2,
// Exceção dentro do intervalo periódico
"external": {
// Flag para exibir a exceção na interface
"show": false,
// Duração do fragmento excluído (em minutos)
"value": 2
}
}
],
"inEveryWeek": true,
"inEveryMonth": true,
"inEveryYears": true
},
{
"id": "918175fd-cc18-4ca5-9bee-c78c61c9415a",
"range": ["2026-01-18T17:00:00.000Z", "2026-01-20T17:00:00.000Z"],
// Sem exceções
"external": [],
// Sem intervalos de tempo internos
"intervals": [],
"inEveryWeek": true,
"inEveryMonth": true,
"inEveryYears": true
}
],
// Flag para visibilidade do atributo na interface
"isVisible": true,
"identifier": "time_interval",
"localizeInfos": {
"en_US": {
"title": "Time interval"
}
},
"receiveValues": true
}
}

  • JSON: Alguns dados em formato JSON.

Exemplo:

{
"type": "json",
"value": {},
"marker": "json",
"position": 17,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Json"
},
"additionalFields": []
}

A interface de preenchimento de conteúdo corresponderá ao tipo de dado selecionado para cada campo de atributo.


💡 Notas Importantes

Validadores

Você pode adicionar validadores para atributos para garantir a qualidade dos dados:

  • Campos obrigatórios.
  • Comprimento mínimo/máximo para texto.
  • Limites de tamanho de arquivo para uploads.
  • Dimensões em pixels para imagens.
  • Intervalos de datas.

Saiba mais: Veja a seção "Validadores" para configuração detalhada.

Conjuntos de Atributos Compartilhados

⚠️ Importante: Se um conjunto de atributos for usado por várias entidades, tenha cuidado ao fazer alterações:

Excluindo um atributo:

  • Remove-o em todos os lugares onde o conjunto é usado.
  • Exclui todo o conteúdo nesse campo.
  • Não pode ser desfeito!

Adicionando um atributo:

  • Adicionado em todos os lugares onde o conjunto é usado.
  • Conteúdo existente inalterado.
  • Novo campo ficará vazio para itens existentes.

Exemplo:

"Informações do Produto" usado por:
- Produtos Físicos.
- Produtos Digitais.
- Serviços.

Excluir o atributo "peso" → Removido de TODOS os três! ⚠️

📊 Tabela de Referência Rápida - Métodos Comuns

MétodoO que fazQuando usar
getAttributes()Obtendo todos os objetos de conjuntos de atributos.
getAttributesByMarker()Obtendo todos os atributos por marcador com dados do conjunto de atributos.
getAttributeSetByMarker()Obtendo um único objeto de conjunto de atributos por marcador.
getSingleAttributeByMarkerSet()Obtendo um atributo com dados do conjunto de atributos.

❓ Perguntas Comuns (FAQ)

Qual é a diferença entre string e text?

  • string - Texto curto, linha única (máx ~255 caracteres). Use para nomes, títulos, emails.
  • text - Texto longo, múltiplos parágrafos, suporta formatação e HTML. Use para descrições, artigos.

Quando devo usar integer vs float?

  • integer - Apenas números inteiros: 1, 2, 100, -5. Use para quantidades, contagens, idades.
  • float - Números decimais: 19.99, 4.5, -0.25. Use para preços, avaliações, medições.
  • real - Como float, mas com maior precisão. Use para cálculos científicos.

Melhor prática: Planeje seus tipos de atributo antes de adicionar conteúdo.


O que acontece se eu excluir um atributo?

  • Você não pode excluir um atributo se ele estiver sendo usado em um conjunto de atributos.

Posso reutilizar o mesmo atributo em diferentes conjuntos de atributos?

Não, cada atributo pertence a um conjunto de atributos. Mas você pode:

  • Criar atributos semelhantes com marcadores diferentes
  • Reutilizar conjuntos de atributos inteiros em várias entidades

O que é o "marker" e por que é importante?

O marker é o identificador técnico que você usa no código:

// No seu código:
product.attributeValues.product_name // ← "product_name" é o marker

// VS o nome (exibido na administração):
"Nome do Produto" // ← Isso é apenas para humanos

Regras para markers:

  • Devem ser únicos
  • Sem espaços (use _)
  • Não podem começar com números
  • Use letras minúsculas
  • Escolha nomes descritivos

Como eu sei qual tipo usar para meus dados?

Pergunte a si mesmo:

  1. É texto?

    • Curto (< 255 caracteres)? → string
    • Longo com formatação? → text
    • Precisa de um título? → textWithHeader
  2. É um número?

    • Sem decimais? → integer
    • Tem decimais? → float
    • Precisão científica? → real
  3. É uma escolha?

    • Escolher uma opção? → radioButton
    • Menu dropdown? → list
  4. É um arquivo?

    • Imagem? → image ou groupOfImages
    • Documento? → file
  5. É uma data?

    • Apenas data? → date
    • Data + hora? → dateTime
    • Período de tempo? → timeInterval

Posso ter atributos aninhados (atributos dentro de atributos)?

Não diretamente, mas você pode usar:

  • Tipo entity para vincular a outros conteúdos
  • Tipo json para armazenar dados estruturados
  • Múltiplos conjuntos de atributos para organizar campos relacionados

Como adiciono regras de validação?

No painel de administração do OneEntry:

  1. Vá para seu conjunto de atributos
  2. Clique em um atributo
  3. Adicione validadores (obrigatório, min/max, regex, etc.)
  4. Salve as alterações

Validadores comuns:

  • Campo obrigatório
  • Comprimento mínimo/máximo
  • Formato de email
  • Formato de URL
  • Limites de tamanho de arquivo
  • Dimensões de imagem

🎓 Melhores Práticas

  • Use marcadores descritivos (product_price em vez de pp)
  • Planeje os tipos de atributo antes de adicionar conteúdo
  • Reutilize conjuntos de atributos sempre que possível
  • Adicione validadores para garantir a qualidade dos dados
  • Documente para que cada atributo serve

Mais informações sobre a interface do usuário do módulo https://doc.oneentry.cloud/docs/attributes/introduction

Definição do módulo AttributesSets


const { AttributesSets } = defineOneEntry(
"sua-url-do-projeto", {
"token": "seu-token-de-aplicativo"
}
);


🔗 Documentação Relacionada