# Les widgets du CMS de Total.js : les utiliser dans une page et écrire les vôtres

> Comment un widget apparaît dans le HTML d’une page (l’attribut data-cms et son JSON), les parties d’un fichier de widget, le marqueur CLASS, rendre un widget côté serveur avec exports.render et installer des widgets par l’API.

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

Un **widget** est un bloc que vous placez dans une page : un titre, une alerte, une galerie. Il porte son propre style, un formulaire pour le configurer dans l’éditeur et, facultativement, du code qui le rend côté serveur. Un widget est un fichier HTML, comme un composant de [Flow](/en/flow/write-a-component/), et le CMS le stocke dans ses métadonnées.

## Un widget dans une page

Dans le HTML d’une page, un widget est un `div` avec deux attributs :

```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` vaut `<widget id>__<configuration>`, où la configuration est un objet JSON écrit avec `encodeURIComponent`. L’éditeur l’écrit ; vous pouvez l’écrire vous-même quand vous générez des pages.
- `data-cms-id` est l’identifiant de l’instance dans la page.

Quand la page est servie, le CMS supprime l’attribut `data-cms`, conserve le HTML qui est à l’intérieur et ajoute à l’en-tête le style de chaque widget de la page. Si le widget n’est pas installé, son bloc est abandonné.

## Les parties d’un fichier de widget

| Partie | À quoi elle sert |
|---|---|
| `<script total>` | les métadonnées et le code serveur : `exports.id`, `name`, `author`, `version`, `preview` (une image ou une data URI), `config` (les valeurs par défaut) et, facultativement, `dependencies`, `install`, `uninstall` et `render` |
| `<style>` | le CSS du widget |
| `<body>` | le design du widget tel que l’éditeur le montre ; les éléments avec la classe `CMS_edit` sont les éditables ; les autres classes `CMS_*` (`CMS_repeat`, `CMS_remove`, `CMS_unwrap`...) sont des marqueurs pour l’éditeur, et le compilateur les supprime avant de servir la page |
| `<settings>` | le formulaire qui modifie `config` dans l’éditeur (des champs jComponent dont le chemin commence par `?.`) et un `<script>` avec `exports.save(config, el)` qui change le design quand la configuration change |
| `<template>` | un modèle facultatif pour le widget |
| `<readme>` | l’aide du widget |

`CLASS` dans le style, les réglages, le modèle et le design est remplacé par une classe propre au widget (`w-` suivi de son id), de sorte que deux widgets ne partagent jamais une règle : dans le widget `alert`, `.CLASS-color1` devient `.w-alert-color1`.

`exports.dependencies` accepte une liste ou une chaîne séparée par des virgules : une adresse finissant par `.js` devient un `<script src>` et une finissant par `.css` un `<link rel="stylesheet">`, ajoutés à l’en-tête de la page.

## Rendre côté serveur

Un widget sans `exports.render` est seulement nettoyé et servi tel quel. Avec `render`, il peut construire son HTML à partir de la configuration :

```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` est la configuration de l’instance, `opt.html` le HTML qui était à l’intérieur du bloc, et `opt.id`, `opt.uid` et `opt.body` le décrivent. `next(html, replace)` donne le HTML à servir ; avec `true` comme second argument, il remplace tout le bloc. Nous avons enregistré ce fichier dans un CMS local et une page avec `data-cms="hello__..."` et `{"text":"mundo"}` est sortie comme `<p class="w-hello">Hello MUNDO</p>`, avec `.w-hello{color:#07c}` dans l’en-tête. Le widget officiel `picture` utilise la même fonction pour ajouter `loading="lazy"` à son image, et `code` pour afficher le code de ses réglages.

`exports.install` et `exports.uninstall` s’exécutent avec la base de données du CMS quand le widget est ajouté, modifié ou supprimé.

## Installer et supprimer des widgets

Le plugin *Widgets* de l’admin importe un fichier ; par l’API, c’est `widgets_save` avec `{ "html": "<file content>", "singleton": true }` (`singleton` ignore le widget s’il existe déjà), `widgets_list`, `widgets_read`, `widgets_detail` et `widgets_remove`. Ils demandent la permission `widgets` (voir [l’API de l’admin](/en/cms/the-admin-api/)). Les 43 widgets officiels sont dans [le dépôt des widgets](/en/cms/the-widgets-repository/).
