# Builder Fields & Acai Attributes ## Nombres de variables El atributo `data-field-label` se convierte a variable removiendo espacios y caracteres especiales (minúsculas). Reglas obligatorias: - Todo elemento editable con `data-field-type` debe incluir también `data-field-label` - Si falta `data-field-label`, el builder puede generar variables temporales o incorrectas y el módulo queda mal configurado - Usa labels descriptivos y estables; no dejes labels vacíos ni genéricos como "Campo" o "Texto" Evita también en `index-base.tpl` las clases Tailwind con valores arbitrarios como `text-[44px]`, `font-['Cinzel']` o `leading-[1.1]`. En este stack pueden romper el parseo/compilación del template. Muévelas a `style.css`. | Label | Variable | |-------|----------| | Categoría Noticia | `categoranoticia` | | Color Principal | `colorprincipal` | | Título Producto | `ttuloproducto` | --- ## Field Types (`data-field-type`) | Type | Element | Returns | |------|---------|---------| | `textfield` | `

` | String | | `headfield` | `

`-`

` | String + variable `_tag` con la etiqueta elegida | | `textbox` | `
` | String multi-línea | | `wysiwyg` | `
` | HTML string | | `link` | `` | URL string (ya incluye barras) | | `upload` | `` | **Array** de `{urlPath, info1, info2, info3, info4}` | | `uploadMulti` | `
  • ` | Itera sobre archivos subidos | | `list` (fijo) | `
    ` | Valor seleccionado | | `list` (tabla) | `
    ` | `num` del registro | | `multiv2` | `
  • ` wrapper | Array de objetos | ### textfield ```html

    Elemento editable

    ``` ### headfield Genera 2 variables: la estándar y otra con sufijo `_tag` con la etiqueta elegida por el usuario. ```html <{{ title_tag | default('h2') }} data-field-type="headfield" data-field-label="Título Sección" class="text-3xl font-bold"> Título de la sección ``` ### textbox ```html
    Texto largo editable
    ``` ### wysiwyg ```html

    Texto con estilos editables

    ``` ### link ```html
    Haz clic aquí ``` ### upload ```html
    ``` Atributos disponibles: - `data-lazy="true"`: Carga perezosa - `data-field-width="1400"`: Ancho máximo sugerido - `data-field-info1="titulo"`: Campo de información adicional (usado como alt) Acceso en Twig: `{{ imagen[0].urlPath }}`, `{{ imagen[0].info1 }}` ### uploadMulti Itera sobre todas las imágenes subidas: ```html
  • {{ uploadMulti.info1 }}
  • ``` ### list (opciones fijas) ```html
    ``` Formato de opciones: `opcion1,opcion2,|opcion3,valor3|opcion4` ### list (tabla) ```html
    {{ record.titulo }}
    ``` - `data-list-table`: Nombre de tabla sin prefijo `cms_` - `data-list-value`: Campo a usar como valor (generalmente `num`) - `data-list-label`: Campo a mostrar como label ### multiv2 — Campos repetibles ```html
    • Nombre del producto
      Descripción del producto
    ``` Uso en Twig — las variables son propiedades del objeto iterado: ```twig {% for record in productos %}

    {{ record.nombre }}

    {{ record.descripcion }}

    {% endfor %} ``` --- ## Acai Attributes ### `c-if` — Renderizado condicional ```html
    {{ subtitle }}
    Grid layout
    ``` ### `c-else` Debe ir inmediatamente después del elemento `c-if`: ```html

    No image available

    ``` ### `c-for` — Iteración sobre array ```html

    {{ item.title }}

    ``` ### `c-for` — Iteración sobre tabla de BD ```html
    • {{ producto.title }}
    ``` Parámetros opcionales: `c-where` (condición SQL), `c-order` (orden), `c-limit` (límite). Equivalente en Twig: ```twig {% for producto in 'productos' | get('visible=1','num desc',10) %}
  • {{ producto.title }}
  • {% endfor %} ``` Dentro del loop: `loop.index` (1-based), `loop.index is odd`, `loop.index is even` ### `c-class` — Clases CSS condicionales ```html
    ``` ### `c-hidden` — Elementos ocultos Elemento que no se renderiza pero puede declarar variables builder: ```html
    ``` ### `c-required` — Campos requeridos condicionales ```html ``` --- ## Definiendo variables con `` ```html {% set gracias = 'apartados' | get('num = 20').0 %} ``` --- ## Incluyendo módulos Para incluir un módulo dentro de otro módulo o sección general, usa el ID del módulo como etiqueta HTML: ```html ``` Ejemplo: ```html ``` El módulo hijo recibe los parámetros como variables en su contexto. --- ## Formularios (`c-form`) Manejo automático de validación, almacenamiento en BD y envío de emails. ```html
    ``` ### Atributos de c-form | Atributo | Descripción | |----------|-------------| | `tableName="'table'"` | Tabla donde almacenar registros | | `mailRecord="['correos', 'ID']"` | Template de email de la tabla `correos` | | `sendTo="'email@domain.com'"` | Destinatarios (separados por coma) | | `sendToClient="'campo_email'"` | Campo con email del cliente para auto-reply | | `captcha="true"` | Google reCAPTCHA | | `honeypot="true"` | Campo oculto anti-spam | | `messageOK="'texto'"` | Mensaje de éxito | | `messageKO="'texto'"` | Mensaje de error | | `redirect="'/path/'"` | Redirección tras envío exitoso | | `attachFiles="true"` | Adjuntar archivos al email | | `showImages="true"` | Mostrar thumbnails en email | | `emailMode="'twig'"` | Email en formato Twig | | `header="'
    ...
    '"` | HTML cabecera del email | | `footer="'
    ...
    '"` | HTML footer del email | | `styles="'body { ... }'"` | CSS para el email | --- ## Componentes Built-in ### Carousel (`c-tns-wrapper`) ```html
    ``` ### Lightbox ```html ``` ### Breadcrumb ```html ``` ### Animate On Scroll (AOS) ```html
    Animated content
    ``` ### Lazy Loading ```html ``` --- ## Puntos importantes 1. **Nombres de variables:** `data-field-label` → sin espacios ni caracteres especiales, minúsculas 2. **Variables en multiv2:** Son propiedades del objeto iterado (`record.nombre`) 3. **Campos upload:** Retornan arrays, no strings (`imagen[0].urlPath`, no `imagen`) 4. **c-if usa `=` no `==`:** `c-if="layout = 'grid'"` (un solo igual) 5. **c-for tabla:** El nombre de tabla va sin prefijo `cms_` 6. **Enlace:** Ya incluye barras, no añadir extras 7. **Checkbox:** Valores `1` o `0`, no `true`/`false` --- ## MCP Tools: Config Vars e Imágenes de Módulos ### Regla importante: Siempre rellenar variables al añadir un módulo Cuando se añade un módulo a una página (con `add_module_to_record`), este queda vacío y no muestra nada visible. **SIEMPRE** hay que llamar a `set_module_config_vars` inmediatamente después para rellenar las variables con contenido de ejemplo coherente con el contexto del sitio. Incluir: - Textos (títulos, descripciones, pretítulos) con contenido relevante al sitio - Valores de listas/selects con una opción válida - Para variables multi (records), crear al menos 2-3 items de ejemplo - Para variables de imagen (upload), usar `generate_image` o `upload_record_image` para que el módulo se vea completo Un módulo sin variables configuradas es invisible en la web. ### Leer variables de un módulo Antes de modificar cualquier módulo, usar `get_module_config_vars` para conocer el estado actual: - **tableName**: tabla del registro padre (ej: `apartados`), SIN prefijo `cms_` - **recordNum**: campo `num` del registro padre (ej: `2`) - **sectionId**: el `section_id` de la instancia del módulo (ej: `6c6d8`) ### Escribir variables de un módulo Usar `set_module_config_vars` con los mismos tableName, recordNum y sectionId. Pasar todos los valores como strings. La respuesta incluye `configVars` con el `recordNum` del registro `builder_custom` creado/actualizado y `uploadFields` para imágenes. **Tipos de almacenamiento (manejado automáticamente):** - `headfield`, `textfield`, `link`, `textbox`, `wysiwyg`, `upload` → se guardan en tabla `builder_custom` - `list`, `checkbox`, `colorpicker` → se guardan directamente en el JSON config-vars (no en builder_custom) No necesitas preocuparte por esto — `set_module_config_vars` lo maneja internamente. Solo pasa los valores como strings. ### Subir imágenes a un módulo El nombre del campo de imagen viene de `builder.json` → `vars.NOMBRE.relations.builder_custom` (ej: `"image1"`). NO es el nombre de la variable (ej: NO `"imagenes"`). **Flujo correcto:** 1. `get_module_config_vars` → obtener el `recordNum` en builder_custom de la variable de imagen 2. `upload_record_image` con: - `tableName`: `"builder_custom"` (siempre, sin prefijo cms_) - `recordId`: el `recordNum` del paso 1 (ej: `"778"`) - `fieldName`: el campo de relations del builder.json (ej: `"image1"`) - `imageUrl`: URL completa accesible desde Docker 3. `reorder_record_uploads` si es necesario — pasar array de upload IDs en el orden deseado 4. `list_record_uploads` para verificar **Errores comunes a evitar:** - NO usar el sectionId como recordId — usar el `num` de builder_custom - NO usar el nombre de la variable como fieldName — usar el campo de relations del builder.json (ej: `image1`, no `imagenes`) - NO poner prefijo `cms_` en tableName