---
title: "Nested Widget Descriptors"
slug: "nested-widget-descriptors"
category: "Patterns"
locale: "es"
reactExample: "pattern-descriptor.tsx"
hosts: "ninox"
---

# Nested Widget Descriptors (Object-Notation)

## AI Defaults (read first)


- **Top-level** Ninox formula: use **`arcCustomLayout({ uniqueId: … })`** (function call) — not a descriptor object.
- **Nested** inside another widget's content slot (`blocks[].value`, table cells, drawing sidebar, kanban cards, …): use **`{ widget, uid, data }`**.
- **`widget`**: internal kebab-case ID (e.g. `"arc-widget-layout"`), **not** `arcCustomLayout`.
- **`uid`**: same rules as `uniqueId` — unique, no spaces/special characters.
- **`data`**: same properties as the function call; use `uid` at the top level instead of `uniqueId` inside `data`.
- **Next-Gen only**: parent **and** child must come from the current **`bundle.js` / profile build** (`arcWidgetManager` v3). **Legacy Ninox-formula widgets do not support this.**
- When unsure whether a widget is Next-Gen: if it only exists as an old Ninox template formula (not in the bundle), use the function call or plain HTML — **never** a descriptor object.


---

# Widgets anidados como objeto JSON

Los mini-widgets y otros widgets se colocan en slots como **objeto JSON puro** — no como HTML pre-renderizado.

Esto es útil en bloques de layout, celdas de tabla, sidebars de drawing y superficies profundamente anidadas.

## Dos notaciones


### Top-Level (campo de fórmula de Ninox)

El punto de entrada sigue siendo una **llamada a función**:

```javascript
arcCustomLayout({
    uniqueId: "dashboard-" + Nr,
    embedded: false,
    fullscreen: true,
    height: "100%",
    direction: "vertical",
    blocks: [ … ]
})
```


### Anidado (contenido en un slot)

En `blocks[].value` (y slots comparables) usas la **notación de descriptor de widget**:

```javascript
{
    widget: "arc-widget-button",
    uniqueId: "open-btn-" + Nr,   // oder kurz: uid: "open-btn-" + Nr
    data: {
        title: "Öffnen",
        height: "20px",
        width: "auto",
        actions: [{ type: "popup", recordId: "42" }]
    }
}
```

Para el ID, el descriptor acepta **ambas notaciones** por igual:
- `uniqueId` — coherente con la configuración raíz
- `uid` — forma corta, igualmente válida

### Correspondencia


| Llamada a función | Descriptor |
|-----------------|------------|
| `arcCustomLayout({ … })` | `widget: "arc-widget-layout"` |
| `uniqueId: "…"` | `uniqueId: "…"` oder `uid: "…"` (top-level, **nicht** in `data`) |
| Todas las demás props | En `data: { … }` |


## Ejemplo completo (Layout → Button)

Ver también [Custom Layout](/docs/ninox/widgets/custom-layout) para bloques de layout anidados.

```javascript
{
    widget: "arc-widget-layout",
    uniqueId: "sidebar-item-" + Nr,   // uid: "sidebar-item-" + Nr wäre gleichwertig
    data: {
        embedded: true,
        direction: "horizontal",
        gap: "10px",
        blocks: [{
            width: "fraction",
            height: "auto",
            value: "Mangel ID"
        }, {
            width: "auto",
            height: "auto",
            value: {
                widget: "arc-widget-button",
                uniqueId: "open-btn-" + Nr,   // uid: "open-btn-" + Nr wäre gleichwertig
                data: {
                    title: "Öffnen",
                    height: "20px",
                    actions: [{ type: "popup", recordId: "42" }]
                }
            }
        }]
    }
}
```


En Ninox, `uniqueId: "sidebar-item-" + Nr` sigue siendo habitual, y `recordId: Nr` en las actions.

## Requisito: bundle Next-Gen

El motor reconoce los objetos descriptor en slots mediante **`append_content`**: si `value` es un objeto con el campo `widget`, llama a `arcWidgetManager.js(widget, uid, data)`.

Esto funciona **solo** si:

1. El **widget padre** proviene del bundle actual y renderiza el slot mediante `append_content`.
2. El **widget hijo** está **registrado** en el mismo bundle.

### Next-Gen (funciona)

- Widgets registrados en el bundle / plantilla de Ninox actuales

### Legacy (**no** funciona)

- El widget existe **solo** como una **fórmula NinoxScript** antigua en el template / en la base de datos (string HTML, sin `arcWidgetManager`)
- El slot espera HTML terminado o un resultado de fórmula — `{ widget: … }` no se interpreta (queda vacío, error en consola o markup roto)

**Aún sin soporte de descriptor:** `arcCustomGrid`, `arcCheckBox`, `arcCustomImage`, `shortNumbers` — estos **no pueden ser** ni padre ni hijo en la notación de descriptor.


## Widgets padre con slots de descriptor

Estos widgets montan descriptores anidados (tienen `append_content`):

| ID de widget | Slots típicos |
|-----------|----------------|
| `arc-widget-layout` | `blocks[].value` |
| `arc-widget-button` | `icon`, `title`, `subtitle`, `prefix`, `suffix` |
| `arc-widget-table` | `table[].columns[].value` |
| `arc-widget-drawing` | `sidebarItem`, `rightSideContent`, contenido de shapes |
| `arc-widget-kanban` | `value` de tarjetas, contenido de swimlanes |
| `arc-widget-select` | `currentValue`, `items[].title` |
| `arc-widget-input` | slots de label/prefix |
| `arc-widget-badge` | contenido del badge |
| `arc-widget-upload` | `container.value` |
| `arc-widget-calendar-week` | contenido de entries |
| `arc-widget-calendar-timeline` | contenido de celdas/entries |
| `arc-widget-calendar-grid` | contenido de celdas |

## Widgets hijo (frecuentemente anidados)

Todos los widgets registrados en el bundle pueden aparecer como **valor de `widget`**, por ejemplo:


| Valor de `widget` | Función de Ninox |
|---------------|----------------|
| `arc-widget-layout` | `arcCustomLayout` |
| `arc-widget-button` | `arcCustomButton` |
| `arc-widget-badge` | `arcCustomBadge` |
| `arc-widget-icon` | `arcCustomIcon` |
| `arc-widget-select` | `arcCustomSelect` |
| `arc-widget-input` | `arcCustomInput` |
| `arc-widget-text` | (mini-widget / Text) |

El **ID de `widget`** está en la tabla de arriba (`arc-widget-button`, `arc-widget-layout`, …).


## ¿Qué formato usar cuándo?


| Situación | Formato |
|-----------|--------|
| Widget raíz en un campo de fórmula de Ninox | `arcCustomXxx({ uniqueId, … })` |
| Contenido en un bloque de layout, celda de tabla, sidebar de drawing, … | `{ widget, uniqueId, data }` oder `{ widget, uid, data }` |
| Widget legacy aún no en el bundle | Llamada a función o HTML — **sin** descriptor |
| Texto plano en un bloque | String (`value: "Text"`) |


## Errores a evitar

- ❌ `widget: "arcCustomLayout"` oder `widget: "ArcWidgetLayout"` — ID incorrecto (CamelCase)
- ❌ Poner `uniqueId` o `uid` **dentro** de `data` — siempre al nivel superior (al mismo nivel que `widget` y `data`)

- ❌ Descriptor en un campo de fórmula top-level sin padre — usa la llamada a función
- ❌ Descriptor como hijo de un layout legacy proveniente de un template antiguo de Ninox


## Ver también

- [Custom Layout](/docs/ninox/widgets/custom-layout) — bloques de layout y slots `value`
- [Button](/docs/ninox/mini-widgets/buttons) — `prefix` / `suffix` como widgets anidados

- [Drawing Pins](/docs/ninox/examples/custom-drawing-pins) — widgets anidados en sidebar/detalle
