# Widgets en el CMS de Total.js: úsalos en una página y escribe los tuyos

> Cómo aparece un widget en el HTML de una página (el atributo data-cms y su JSON), las partes de un archivo de widget, el marcador CLASS, renderizar un widget en el servidor con exports.render e instalar widgets mediante la API.

Framework: cms
Product: CMS (cms@8071e48)
Language: es
Content-SHA256: dc6b1f05dcdefe6886aeea8909b0b88c23ca598847f5f4c9ea9f685afe445eed
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: 
Review: not-recorded

Un **widget** es un bloque que colocas en una página: un titular, un aviso, una galería. Lleva su propio estilo, un formulario para configurarlo en el editor y, opcionalmente, código que lo renderiza en el servidor. Un widget es un archivo HTML, como un componente de [Flow](/en/flow/write-a-component/), y el CMS lo guarda en sus metadatos.

## Un widget dentro de una página

En el HTML de una página, un widget es un `div` con dos atributos:

```html
<div data-cms="headline__%7B%22h%22%3A%22h1%22%2C%22align%22%3A%22left%22%7D" data-cms-id="h1">
	<h1 class="w-headline-h">Hello CMS</h1>
	<p>Some text</p>
</div>
```

- `data-cms` es `<widget id>__<configuration>`, donde la configuración es un objeto JSON escrito con `encodeURIComponent`. Lo escribe el editor; puedes escribirlo tú cuando generes páginas.
- `data-cms-id` es el identificador de la instancia en la página.

Cuando se sirve la página, el CMS elimina el atributo `data-cms`, conserva el HTML que hay dentro y añade a la cabecera el estilo de cada widget de la página. Si el widget no está instalado, su bloque se descarta.

## Las partes de un archivo de widget

| Parte | Para qué sirve |
|---|---|
| `<script total>` | los metadatos y el código del servidor: `exports.id`, `name`, `author`, `version`, `preview` (una imagen o un data URI), `config` (los valores por defecto) y, opcionalmente, `dependencies`, `install`, `uninstall` y `render` |
| `<style>` | el CSS del widget |
| `<body>` | el diseño del widget tal como lo muestra el editor; los elementos con la clase `CMS_edit` son los editables; las demás clases `CMS_*` (`CMS_repeat`, `CMS_remove`, `CMS_unwrap`...) son marcadores para el editor, y el compilador las elimina antes de servir la página |
| `<settings>` | el formulario que edita `config` en el editor (entradas de jComponent cuya ruta empieza por `?.`) y un `<script>` con `exports.save(config, el)` que cambia el diseño cuando cambia la configuración |
| `<template>` | una plantilla opcional para el widget |
| `<readme>` | la ayuda del widget |

`CLASS` en el estilo, los ajustes, la plantilla y el diseño se sustituye por una clase que pertenece al widget (`w-` seguido de su id), de modo que dos widgets nunca comparten una regla: en el widget `alert`, `.CLASS-color1` pasa a ser `.w-alert-color1`.

`exports.dependencies` acepta una lista o una cadena separada por comas: una dirección que termina en `.js` se convierte en un `<script src>` y una que termina en `.css` en un `<link rel="stylesheet">`, añadidos a la cabecera de la página.

## Renderizar en el servidor

Un widget sin `exports.render` solo se limpia y se sirve tal cual. Con `render` puede construir su HTML a partir de la configuración:

```html
<script total>

	exports.id = 'hello';
	exports.name = 'Hello';
	exports.author = 'Me';
	exports.version = '1';
	exports.config = { text: 'world' };

	exports.render = function(opt, next) {
		next('<p class="w-hello">Hello ' + (opt.config.text || '').toUpperCase() + '</p>', true);
	};

</script>

<style>
	.CLASS { color: #07c; }
</style>

<body>
	<p class="CLASS CMS_edit">Hello world</p>
</body>
```

`opt.config` es la configuración de la instancia, `opt.html` el HTML que había dentro del bloque, y `opt.id`, `opt.uid` y `opt.body` lo describen. `next(html, replace)` entrega el HTML que se sirve; con `true` como segundo argumento sustituye todo el bloque. Guardamos este archivo en un CMS local y una página con `data-cms="hello__..."` y `{"text":"mundo"}` salió como `<p class="w-hello">Hello MUNDO</p>`, con `.w-hello{color:#07c}` en la cabecera. El widget oficial `picture` usa la misma función para añadir `loading="lazy"` a su imagen, y `code` para imprimir el código de sus ajustes.

`exports.install` y `exports.uninstall` se ejecutan con la base de datos del CMS cuando se añade, cambia o elimina el widget.

## Instalar y eliminar widgets

El plugin *Widgets* del admin importa un archivo; por la API es `widgets_save` con `{ "html": "<file content>", "singleton": true }` (`singleton` omite el widget si ya existe), `widgets_list`, `widgets_read`, `widgets_detail` y `widgets_remove`. Necesitan el permiso `widgets` (consulta [la API del admin](/en/cms/the-admin-api/)). Los 43 widgets oficiales están en [el repositorio de widgets](/en/cms/the-widgets-repository/).
