Saltar al contenido principal

Introducción

Define campos personalizados para tu contenido sin tocar el código.

🎯 ¿Qué hace este módulo?

El módulo AttributesSets te permite usar campos personalizados para tu contenido (productos, páginas, formularios, etc.) sin codificarlos en tu aplicación.

Piénsalo como un constructor de formularios para tus datos: defines qué campos necesitas y OneEntry se encarga del resto.

📖 Explicación Simple

Imagina que estás construyendo una tienda en línea. Cada producto necesita:

  • Nombre (texto).
  • Precio (número).
  • Imagen (foto).
  • Descripción (texto largo).
  • Categoría (desplegable).

En lugar de codificar estos campos en tu aplicación, usas Attributes para definirlos en el panel de administración de OneEntry. Luego puedes:

  • Agregar nuevos campos en cualquier momento (¡sin cambios de código!).
  • Reutilizar campos en diferentes tipos de contenido.
  • Cambiar tipos de campo sin redeplegar.
  • Gestionar toda la estructura de contenido en un solo lugar.

Ejemplo del 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!

✨ Conceptos Clave

¿Qué es un Atributo?

Un atributo es un campo único que almacena datos.

Ejemplos:

  • Nombre del producto (cadena).
  • Precio del producto (flotante).
  • Imagen del producto (imagen).
  • Fecha de publicación (fecha).

¿Qué es un Conjunto de Atributos?

Un conjunto de atributos es una colección de atributos que definen una estructura.

Ejemplo: Conjunto de Atributos del Producto

- name (string)
- price (float)
- description (text)
- images (group of images)
- category (list)
- inStock (integer)

¿Por qué Usar Conjuntos de Atributos?

❌ Sin Atributos✅ Con Atributos
Campos codificadosCampos dinámicos
Cambios de código necesariosEditar en el panel de administración
Se requiere redepliegueActualizaciones en vivo
Estructura rígidaEstructura flexible
Código duplicadoConjuntos reutilizables

📋 Lo Que Necesitas Saber

Tres Términos Importantes

TérminoQué EsEjemplo
MarcadorIdentificador de código único"product_name"
TipoQué tipo de datos almacena"string", "integer", "image"
ValorValor del atributo"Nombre del Producto"

Importante sobre los Marcadores:

  • Deben ser únicos
  • No se permiten espacios (usa _ en su lugar)
  • No pueden comenzar con un número
  • Usa minúsculas para consistencia

Ejemplos:

  • ✅ Bueno: product_name, price_usd, main_image
  • ❌ Malo: product name, 2nd_price, Product Name

📚 Tipos de Datos Disponibles

Los atributos pueden almacenar diferentes tipos de datos. Elige el tipo correcto para cada campo.

Tabla de Referencia Rápida

TipoMejor ParaEjemplo de Uso
stringTexto cortoNombre del producto, correo
textTexto largo formateadoPublicación de blog, descripción
textWithHeaderTexto con títuloSecciones de artículos
integerNúmeros enterosCantidad, edad
realDecimales de alta precisiónDatos científicos
floatNúmeros decimalesPrecio, calificación
dateSolo la fechaFecha de nacimiento, fecha límite
dateTimeFecha + horaInicio del evento, publicado en
timeSolo la horaHorario de apertura
fileCualquier archivoPDF, documento
imageImagen únicaAvatar, logo
groupOfImagesMúltiples imágenesGalería de fotos
radioButtonOpción únicaTamaño (S/M/L)
listSelección desplegablePaís, categoría
entityEnlace a otro contenidoProductos relacionados
timeIntervalRango de fechasPeríodo de promoción
jsonDatos estructurados personalizadosRespuesta de API

🔍 Descripciones Detalladas de Tipos de Datos

Tipos de Texto

Cuándo usar qué:

  • string - Línea única, menos de 255 caracteres (nombre, correo, título)
  • text - Múltiples párrafos, soporta formato (artículos, descripciones)
  • textWithHeader - Texto que necesita un encabezado (secciones de blog, preguntas frecuentes)

Tipos de Números

Cuándo usar qué:

  • integer - Sin decimales necesarios (edad, cantidad, vistas)
  • float - Decimales estándar (precio $19.99, calificación 4.5)
  • real - Precisión extra necesaria (cálculos científicos)

Tipos de Fecha/Hora

Cuándo usar qué:

  • date - Solo el día (cumpleaños, fecha límite)
  • time - Solo la hora (horario comercial, hora de cita)
  • dateTime - Ambos necesarios (inicio del evento, artículo publicado)
  • timeInterval - Período entre fechas (duración de la venta, fechas de vacaciones)

Tipos de Archivo e Imagen

Cuándo usar qué:

  • file - Cualquier documento (PDF, DOC, ZIP)
  • image - Una imagen (foto de producto, avatar)
  • groupOfImages - Múltiples imágenes (galería, imágenes de producto)

Tipos de Selección

Cuándo usar qué:

  • radioButton - Elegir solo UNA opción (Sí/No, Tamaño S/M/L)
  • list - Desplegable con opciones (País, Categoría, Estado)

Tipos Avanzados

  • entity - Enlace a otras páginas/productos (Artículos Relacionados, Categorías)
  • json - Almacenar estructuras de datos complejas (respuestas de API, configuraciones)

📖 Ejemplos de Tipos de Datos

A continuación se presentan ejemplos técnicos de la estructura de cada tipo de dato.

💡 Los datos devueltos en el conjunto de atributos no incluyen los valores reales de los atributos, ya que estos valores están contenidos dentro de entidades específicas como páginas, productos, etc. La única excepción es el tipo de atributo timeInterval. Este atributo puede tener valores marcando la casilla correspondiente en el panel de administración

Haz clic para ver todos los ejemplos de tipos de datos

Referencia de Tipos de Datos

Los tipos de datos pueden ser de los siguientes tipos:

  • String: Texto simple, por ejemplo, "¡Hola, mundo!".

Ejemplo:

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

  • Text: Texto más largo, a menudo formateado, por ejemplo, un artículo o una carta.

Ejemplo:

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

  • Texto con Encabezado: Texto con un encabezado que se puede usar para denotar un tema o categoría.

Ejemplo:

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

  • Integer: Un número entero, por ejemplo, 5, 100, -2.

Ejemplo:

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

  • Real: Lo mismo que Float, pero con mayor precisión.

Ejemplo:

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

  • Float: Un tipo de dato para números de punto flotante que pueden tener una parte decimal, por ejemplo, 3.14, 1.5, -0.25.

Ejemplo:

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

  • Fecha y Hora: Una combinación de fecha y hora, por ejemplo, 2023-10-27 10:00:00.

Ejemplo:

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

  • Fecha: Una fecha, por ejemplo, 2023-10-27.

Ejemplo:

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

  • Hora: Una hora, por ejemplo, 10:00:00.

Ejemplo:

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

  • Archivo: Cualquier archivo en tu computadora, por ejemplo, un documento, imagen, música.

Ejemplo:

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

  • Imagen: Una imagen, por ejemplo, una fotografía, dibujo.

Ejemplo:

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

  • Grupo de Imágenes: Una colección de imágenes, por ejemplo, un álbum de fotos.

Ejemplo:

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

  • Botón de Opción: Un botón de selección del cual solo se puede elegir una opción.

Ejemplo:

{
"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: Una lista de elementos, por ejemplo, una lista de compras.

Ejemplo:

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

  • Entidad: Una entidad que representa un objeto.

Ejemplo:

{
"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 tiempo: Un calendario flexible con una interfaz fácil de usar para gestionar datos de intervalos de tiempo.

Ejemplo:

{
"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: Algunos datos en formato JSON.

Ejemplo:

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

La interfaz de llenado de contenido corresponderá al tipo de dato seleccionado para cada campo de atributo.


💡 Notas Importantes

Validadores

Puedes agregar validadores para atributos para asegurar la calidad de los datos:

  • Campos requeridos.
  • Longitud mínima/máxima para texto.
  • Límites de tamaño de archivo para cargas.
  • Dimensiones en píxeles para imágenes.
  • Rangos de fechas.
Haz clic para ver ejemplos de validadores
  • requiredValidator: Requiere que se ingrese un valor.

Ejemplo:

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

  • defaultValueValidator:

Ejemplo:

{
"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"
}
]
}

Aprende más: Consulta la sección Validadores para una configuración detallada.

Conjuntos de Atributos Compartidos

⚠️ Importante: Si un conjunto de atributos es utilizado por múltiples entidades, ten cuidado al hacer cambios:

Agregar un atributo:

  • Se añadirá a todas las entidades que usen el conjunto.
  • El contenido existente permanece sin cambios.
  • El nuevo campo estará vacío para los elementos existentes.

Eliminar un atributo:

  • Se eliminará de todas las entidades que usen el conjunto.
  • Los valores existentes se eliminarán permanentemente.

Ejemplo:

"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! ⚠️

📊 Tabla de Referencia Rápida - Métodos Comunes

MétodoQué Hace
getAttributes()Obtener todos los objetos de conjuntos de atributos.
getAttributesByMarker()Obtener todos los atributos por marcador con datos del conjunto de atributos.
getAttributeSetByMarker()Obtener un solo objeto de conjunto de atributos por marcador.
getSingleAttributeByMarkerSet()Obtener un atributo con datos del conjunto de atributos.

❓ Preguntas Comunes (FAQ)

¿Cuál es la diferencia entre string y text?

  • string - Texto corto, línea única (máx. ~255 caracteres). Usar para nombres, títulos, correos.
  • text - Texto largo, múltiples párrafos, soporta formato y HTML. Usar para descripciones, artículos.

¿Cuándo debo usar integer vs float?

  • integer - Solo números enteros: 1, 2, 100, -5. Usar para cantidades, conteos, edades.
  • float - Números decimales: 19.99, 4.5, -0.25. Usar para precios, calificaciones, medidas.
  • real - Como float pero con mayor precisión. Usar para cálculos científicos.

Mejor práctica: Planifica tus tipos de atributos antes de agregar contenido.


¿Qué sucede si elimino un atributo?

  • No puedes eliminar un atributo si se utiliza en un conjunto de atributos.

¿Puedo reutilizar el mismo atributo en diferentes conjuntos de atributos?

No, cada atributo pertenece a un conjunto de atributos. Pero puedes:

  • Crear atributos similares con diferentes marcadores
  • Reutilizar conjuntos de atributos completos en múltiples entidades

¿Qué es el "marcador" y por qué es importante?

El marcador es el identificador técnico que usas en el 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

Reglas para los marcadores:

  • Deben ser únicos
  • Sin espacios (usa _)
  • No pueden comenzar con números
  • Usa minúsculas
  • Elige nombres descriptivos

¿Cómo sé qué tipo usar para mis datos?

Pregúntate:

  1. ¿Es texto?

    • ¿Corto (< 255 caracteres)? → string
    • ¿Largo con formato? → text
    • ¿Necesita un título? → textWithHeader
  2. ¿Es un número?

    • ¿Sin decimales? → integer
    • ¿Con decimales? → float
    • ¿Precisión científica? → real
  3. ¿Es una elección?

    • ¿Elegir una opción? → radioButton
    • ¿Menú desplegable? → list
  4. ¿Es un archivo?

    • ¿Imagen? → image o groupOfImages
    • ¿Documento? → file
  5. ¿Es una fecha?

    • ¿Solo fecha? → date
    • ¿Fecha + hora? → dateTime
    • ¿Período de tiempo? → timeInterval

¿Puedo tener atributos anidados (atributos dentro de atributos)?

Sí, puedes usar Campos Adicionales


¿Cómo agrego reglas de validación?

En el panel de administración de OneEntry:

  1. Ve a tu conjunto de atributos
  2. Haz clic en un atributo
  3. Agrega validadores (requerido, min/max, regex, etc.)
  4. Guarda los cambios

Aprende más: Consulta la sección Validadores para una configuración detallada.


🎓 Mejores Prácticas

  • Usa marcadores descriptivos (product_price no pp)
  • Planifica los tipos de atributos antes de agregar contenido
  • Reutiliza conjuntos de atributos cuando sea posible
  • Agrega validadores para asegurar la calidad de los datos
  • Documenta para qué es cada atributo

Más información sobre la interfaz de usuario del módulo https://doc.oneentry.cloud/docs/attributes/introduction

Definición del módulo AttributesSets


const { AttributesSets } = defineOneEntry(
"tu-url-del-proyecto", {
"token": "tu-token-de-aplicación"
}
);


🔗 Documentación Relacionada