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 generador de formularios para tus datos: tú 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 redeployar.
- Gestionar toda la estructura de contenido en un solo lugar.
Ejemplo del mundo real:
Sin Attributes (codificado):
- Código: const product = { name: 'Nombre del producto', price: 150, image: '', description: '' }
- Para agregar el campo "color" → Cambiar código, redeploy, esperar.
Con Attributes (dinámico):
- Código: const { name, price, image, description } = product
- Panel de administración: Agregar atributo "color".
- El código incluye automáticamente el nuevo campo.
- Código: const { name, price, image, description, color } = product
- ¡No se necesita despliegue!
✨ 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 (cadena)
- price (flotante)
- description (texto)
- images (grupo de imágenes)
- category (lista)
- inStock (entero)
¿Por qué Usar Conjuntos de Atributos?
| ❌ Sin Attributes | ✅ Con Attributes |
|---|---|
| Campos codificados | Campos dinámicos |
| Cambios de código necesarios | Editar en el panel de administración |
| Se requiere redeploy | Actualizaciones en vivo |
| Estructura rígida | Estructura flexible |
| Código duplicado | Conjuntos reutilizables |
📋 Lo Que Necesitas Saber
Tres Términos Importantes
| Término | Qué Es | Ejemplo |
|---|---|---|
| Marker | Identificador de código único | "product_name" |
| Type | Qué tipo de datos almacena | "string", "integer", "image" |
| Value | Valor del atributo | "Nombre del Producto" |
Importante sobre los Markers:
- 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
| Tipo | Mejor Para | Ejemplo de Uso |
|---|---|---|
| string | Texto corto | Nombre del producto, email |
| text | Texto largo formateado | Publicación de blog, descripción |
| textWithHeader | Texto con título | Secciones de artículos |
| integer | Números enteros | Cantidad, edad |
| real | Decimales de alta precisión | Datos científicos |
| float | Números decimales | Precio, calificación |
| date | Solo la fecha | Fecha de nacimiento, fecha límite |
| dateTime | Fecha + hora | Inicio del evento, publicado en |
| time | Solo la hora | Horarios de apertura |
| file | Cualquier archivo | PDF, documento |
| image | Imagen única | Avatar, logo |
| groupOfImages | Múltiples imágenes | Galería de fotos |
| radioButton | Opción única | Tamaño (S/M/L) |
| list | Selección desplegable | País, categoría |
| entity | Enlace a otro contenido | Productos relacionados |
| timeInterval | Rango de fechas | Período de promoción |
| json | Datos estructurados personalizados | Respuesta de API |
🔍 Descripciones Detalladas de Tipos de Datos
Tipos de Texto
Cuándo usar qué:
- string - Línea única, menos de 255 caracteres (nombre, email, título)
- text - Múltiples párrafos, soporta formateo (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 (horas de negocio, 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)
📖 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": []
}
- Text with Header: 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": []
}
- Date and Time: 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": []
}
- Date: Una fecha, por ejemplo, 2023-10-27.
Ejemplo:
{
"type": "date",
"value": {},
"marker": "date",
"position": 8,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Date"
},
"additionalFields": []
}
- Time: Una hora, por ejemplo, 10:00:00.
Ejemplo:
{
"type": "date",
"value": {},
"marker": "date",
"position": 8,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Date"
},
"additionalFields": []
}
- File: 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": []
}
- Image: Una imagen, por ejemplo, una fotografía, un dibujo.
Ejemplo:
{
"type": "image",
"value": {},
"marker": "image",
"position": 11,
"listTitles": [],
"validators": {
"sizeInPixelsValidator": {
"maxX": "500",
"maxY": "500"
}
},
"localizeInfos": {
"title": "Image"
},
"additionalFields": []
}
- Group of Images: 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": []
}
- Radio Button: Un botón de selección del que 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": []
}
- List: 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": "Valor Adicional"
},
"position": 3
}
],
"validators": {},
"localizeInfos": {
"title": "List"
},
"additionalFields": []
}
- Entity: Una entidad que representa un objeto.
Ejemplo:
{
"type": "entity",
"value": {},
"marker": "entity",
"position": 15,
"listTitles": [
{
"title": "Productos",
"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": "Error",
"value": {
"id": 2,
"depth": 0,
"parentId": null,
"position": 3,
"selected": true
}
}
],
"validators": {},
"localizeInfos": {
"title": "Entity"
},
"additionalFields": [
{
"type": "string",
"value": "Campo de Prueba",
"marker": "test_field"
}
]
}
- Time interval: 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 de grupos de valores, cada uno vinculado a un intervalo específico (a través de intervalId). Este array se forma cuando Recibir valores está habilitado en CMS
{
// Registros de tiempo específicos aplicables a las fechas especificadas
"values": [
{
// Identificador único del registro
"id": "1dc1787d-acc3-4315-a45d-52166c72e577",
// Rango de fechas (inclusive) al que se aplica este registro
"dates": ["2025-11-27T00:00:00.000Z", "2025-11-27T00:00:00.000Z"],
// Array de franjas horarias en formato [[inicio, fin], ...]
"times": [
[
// Inicio de la franja horaria (horas y minutos)
{
"hours": 19,
"minutes": 18
},
// Fin de la franja horaria
{
"hours": 21,
"minutes": 19
}
]
],
// Reservado (no utilizado en la implementación actual)
"intervals": [],
// Excepciones — segmentos de tiempo excluidos del horario en la fecha especificada
"exceptions": [
{
// Fecha de excepción
"date": "2025-12-17T17:00:00.000Z",
// Array de segmentos de tiempo excluidos
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
// Referencia al intervalo del array `intervals`
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6",
// Bandera para recurrencia semanal (en el día correspondiente de la semana)
"inEveryWeek": true
},
{
"id": "cfa187d3-0284-4e0d-8206-7b353cf47110",
"dates": ["2025-12-18T00:00:00.000Z", "2025-12-18T00:00:00.000Z"],
// Array de franjas horarias en formato [[inicio, fin], ...]
"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"],
// Sin franjas horarias
"times": [],
// Reglas dinámicas para la expansión del horario
"external": [
{
// Fecha base para calcular el evento recurrente
"date": "2026-01-15T00:00:00.000Z",
// El evento se repite cada mes en este día
"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",
// Bandera para recurrencia semanal
"inEveryWeek": true,
// Bandera para recurrencia mensual
"inEveryMonth": true,
// Bandera para recurrencia anual
"inEveryYears": true
}
],
// Referencia al intervalo del 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 plantillas de intervalos de tiempo
{
// Identificador único de la plantilla de intervalo
"id": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6",
"range": [
// Rango principal de aplicabilidad del intervalo
"2025-11-26T17:00:00.000Z",
"2025-11-26T17:00:00.000Z"
],
// Excepciones a nivel de todo el intervalo
"external": [
{
"date": "2025-12-17T17:00:00.000Z",
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
// Franjas horarias internas (períodos de trabajo/activos)
"intervals": [
{
"id": "01fea594-9933-47ac-af0a-ec0e0884f618",
// Fin de la franja horaria
"end": {
"hours": 21,
"minutes": 19
},
// Inicio de la franja horaria
"start": {
"hours": 19,
"minutes": 18
},
// Duración del bloque recurrente (en minutos); null — sin periodicidad
"period": null
},
{
"id": "22ba24af-1fae-4422-8c92-0635b684a306",
"end": {
"hours": 0,
"minutes": 29
},
"start": {
"hours": 0,
"minutes": 25
},
// Periodicidad: las franjas horarias se repiten con un paso de 2 minutos
"period": 2,
// Excepción dentro de la franja periódica
"external": {
// Bandera para mostrar la excepción en la interfaz
"show": false,
// Duración del fragmento excluido (en 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"],
// Sin excepciones
"external": [],
// Sin franjas horarias internas
"intervals": [],
"inEveryWeek": true,
"inEveryMonth": true,
"inEveryYears": true
}
],
// Bandera para la visibilidad del atributo en la interfaz
"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": "Error personalizado",
"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 agregará 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:
Conjunto de atributos "Información del Producto" utilizado por:
- Productos Físicos
- Productos Digitales
- Servicios
Agregar atributo "peso" → ¡Agregado a los TRES!
Eliminar atributo "peso" → ¡Eliminado de los TRES! ⚠️
📊 Tabla de Referencia Rápida - Métodos Comunes
| Método | Qué 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 electrónicos.
- text - Texto largo, múltiples párrafos, soporta formateo 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 solo conjunto de atributos. Pero puedes:
- Crear atributos similares con diferentes markers
- Reutilizar conjuntos de atributos completos en múltiples entidades
¿Qué es el "marker" y por qué es importante?
El marker es el identificador técnico que usas en el código:
// En tu código:
product.attributeValues.product_name // ← "product_name" es el marker
// VS el nombre (mostrado en administración):
"Nombre del Producto" // ← Esto es solo para humanos
Reglas para markers:
- Deben ser únicos
- Sin espacios (usar
_) - No pueden comenzar con números
- Usar minúsculas
- Elegir nombres descriptivos
¿Cómo sé qué tipo usar para mis datos?
Pregúntate:
-
¿Es texto?
- ¿Corto (< 255 caracteres)? →
string - ¿Largo con formateo? →
text - ¿Necesita un título? →
textWithHeader
- ¿Corto (< 255 caracteres)? →
-
¿Es un número?
- ¿Sin decimales? →
integer - ¿Con decimales? →
float - ¿Precisión científica? →
real
- ¿Sin decimales? →
-
¿Es una elección?
- ¿Elegir una opción? →
radioButton - ¿Menú desplegable? →
list
- ¿Elegir una opción? →
-
¿Es un archivo?
- ¿Imagen? →
imageogroupOfImages - ¿Documento? →
file
- ¿Imagen? →
-
¿Es una fecha?
- ¿Solo fecha? →
date - ¿Fecha + hora? →
dateTime - ¿Período de tiempo? →
timeInterval
- ¿Solo fecha? →
¿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:
- Ve a tu conjunto de atributos
- Haz clic en un atributo
- Agrega validadores (requerido, min/max, regex, etc.)
- Guarda los cambios
Aprende más: Consulta la sección Validadores para una configuración detallada.
🎓 Mejores Prácticas
- Usa markers descriptivos (
product_pricenopp) - 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( "your-project-url", { "token": "your-app-token" });
🔗 Documentación Relacionada
- Módulo de Productos - Usa conjuntos de atributos para datos de productos
- Módulo de Páginas - Usa conjuntos de atributos para contenido de páginas
- Módulo de Bloques - Usa conjuntos de atributos para bloques reutilizables
- Módulo de Formularios - Crea formularios con campos personalizados