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.
  • Alterar tipos de campos sem precisar redeployar.
  • Gerenciar toda a estrutura de conteúdo em um só lugar.

Exemplo do mundo real:

Without Attributes (hardcoded):
- Code: const product = { name: 'Product name', price: 150, image: '', description: '' }
- To add "color" field → Change code, redeploy, wait.

With Attributes (dynamic):
- Code: const { name, price, image, description } = product
- Admin panel: Add "color" attribute.
- Code automatically includes new field.
- Code: const { name, price, image, description, color } = product
- No deployment needed!

✨ 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 (group of images)
- category (list)
- inStock (integer)

Por que usar Conjuntos de Atributos?

❌ Sem Atributos✅ Com Atributos
Campos codificadosCampos dinâmicos
Mudanças de código necessáriasEdição 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
  • Espaços não são 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

📚 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 da 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 da API, configurações)

📖 Exemplos de Tipos de Dados

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

💡 Os dados retornados no conjunto de atributos não incluem os valores reais dos atributos, pois esses valores estão contidos em entidades específicas, como páginas, produtos, etc. A única exceção é o tipo de atributo timeInterval. Este atributo pode ter valores marcando a caixa correspondente no painel de administração

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": []
}

  • Texto com Cabeçalho: 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": []
}

  • Data e Hora: 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": []
}

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

Exemplo:

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

  • Hora: Uma hora, por exemplo, 10:00:00.

Exemplo:

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

  • Arquivo: 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": []
}

  • Imagem: 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": []
}

  • Grupo de Imagens: 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": []
}

  • Botão de Rádio: 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": []
}

  • Lista: 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": "Additional Value"
},
"position": 3
}
],
"validators": {},
"localizeInfos": {
"title": "List"
},
"additionalFields": []
}

  • Entidade: Uma entidade representando um objeto.

Exemplo:

{
"type": "entity",
"value": {},
"marker": "entity",
"position": 15,
"listTitles": [
{
"title": "Products",
"value": {
"id": 1,
"depth": 0,
"parentId": null,
"position": 1,
"selected": true
}
},
{
"title": "Normal Page",
"value": {
"id": 4,
"depth": 0,
"parentId": null,
"position": 2,
"selected": true
}
},
{
"title": "Error",
"value": {
"id": 2,
"depth": 0,
"parentId": null,
"position": 3,
"selected": true
}
}
],
"validators": {},
"localizeInfos": {
"title": "Entity"
},
"additionalFields": [
{
"type": "string",
"value": "Test Field",
"marker": "test_field"
}
]
}

  • Intervalo de tempo: 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 of value groups, each linked to a specific interval (via intervalId). This array is formed when Receive values is enabled in CMS
{
// Specific time records applicable to the specified dates
"values": [
{
// Unique record identifier
"id": "1dc1787d-acc3-4315-a45d-52166c72e577",
// Date range (inclusive) to which this record applies
"dates": ["2025-11-27T00:00:00.000Z", "2025-11-27T00:00:00.000Z"],
// Array of time slots in format [[start, end], ...]
"times": [
[
// Start of time slot (hours and minutes)
{
"hours": 19,
"minutes": 18
},
// End of time slot
{
"hours": 21,
"minutes": 19
}
]
],
// Reserved (not used in current implementation)
"intervals": [],
// Exceptions — time segments excluded from the schedule on the specified date
"exceptions": [
{
// Exception date
"date": "2025-12-17T17:00:00.000Z",
// Array of excluded time segments
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
// Reference to interval from the `intervals` array
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6",
// Flag for weekly recurrence (on the corresponding day of the week)
"inEveryWeek": true
},
{
"id": "cfa187d3-0284-4e0d-8206-7b353cf47110",
"dates": ["2025-12-18T00:00:00.000Z", "2025-12-18T00:00:00.000Z"],
// Array of time slots in format [[start, end], ...]
"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"],
// No time slots
"times": [],
// Dynamic rules for schedule expansion
"external": [
{
// Base date for calculating recurring event
"date": "2026-01-15T00:00:00.000Z",
// Event repeats every month on this day
"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 for weekly recurrence
"inEveryWeek": true,
// Flag for monthly recurrence
"inEveryMonth": true,
// Flag for yearly recurrence
"inEveryYears": true
}
],
// Reference to interval from the `intervals` array
"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 of time interval templates
{
// Unique identifier of interval template
"id": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6",
"range": [
// Main range of interval applicability
"2025-11-26T17:00:00.000Z",
"2025-11-26T17:00:00.000Z"
],
// Exceptions at the entire interval level
"external": [
{
"date": "2025-12-17T17:00:00.000Z",
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
// Internal time slots (working/active periods)
"intervals": [
{
"id": "01fea594-9933-47ac-af0a-ec0e0884f618",
// End of time slot
"end": {
"hours": 21,
"minutes": 19
},
// Start of time slot
"start": {
"hours": 19,
"minutes": 18
},
// Duration of repeating block (in minutes); null — no periodicity
"period": null
},
{
"id": "22ba24af-1fae-4422-8c92-0635b684a306",
"end": {
"hours": 0,
"minutes": 29
},
"start": {
"hours": 0,
"minutes": 25
},
// Periodicity: time slots repeat with 2-minute step
"period": 2,
// Exception inside periodic slot
"external": {
// Flag for displaying exception in the interface
"show": false,
// Duration of excluded fragment (in minutes)
"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"],
// No exceptions
"external": [],
// No internal time slots
"intervals": [],
"inEveryWeek": true,
"inEveryMonth": true,
"inEveryYears": true
}
],
// Flag for attribute visibility in the 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.
Clique para ver exemplos de validadores
  • requiredValidator: Exige que um valor seja inserido.

Exemplo:

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

  • defaultValueValidator:

Exemplo:

{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"defaultValueValidator": {
"customErrorText": "Custom error",
"fieldDefaultValue": "usd",
"fieldDefaultValue2": "",
},
},
"localizeInfos": {
"title": "String"
},
"additionalFields": [
{
"type": "integer",
"value": "10",
"marker": "extra"
}
]
}

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:

Adicionando um atributo:

  • Ele será adicionado a todas as entidades que usam o conjunto.
  • O conteúdo existente permanece inalterado.
  • O novo campo ficará vazio para itens existentes.

Removendo um atributo:

  • Ele será removido de todas as entidades que usam o conjunto.
  • Os valores existentes serão permanentemente excluídos.

Exemplo:

"Product Info" attribute set used by:
- Physical Products
- Digital Products
- Services

Adding "weight" attribute → Added to ALL three!
Removing "weight" attribute → Removed from ALL three! ⚠️

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

MétodoO que faz
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:

// In your code:
product.attributeValues.product_name // ← "product_name" is the marker

// VS the name (shown in admin):
"Product Name" // ← This is just for humans

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 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)?

Sim, você pode usar Campos Adicionais


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

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


🎓 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 quando 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