---
url: 'https://dxpr.com/it/hc/documentation/learn-dxpr-builder/development/custom-elements'
title: 'Creare elementi personalizzati | DXPR'
author:
  name: Jurriaan
  url: 'https://dxpr.com/users/jurriaan'
date: '2026-10-24T03:04:16+00:00'
updated: '2026-10-24T09:09:48+00:00'
copyright: 'Copyright DXPR. All rights reserved.'
type: article
summary: |-
  Ogni elemento di DXPR Builder è un oggetto JavaScript inserito in
  window.dxprBuilder.dxpr_elements. L’editor trasforma ogni oggetto
  in una classe di elemento con le schede Style e Animation già
  collegate. Questa pagina mostra come sono definiti gli elementi inclusi in
  dxpr_builder/dxpr_elements.js, come un modulo aggiunge la sua
  definizione all’editor e come appare l’HTML risultante.
  Non esistono modelli Twig lato server per elemento; gli elementi
  sono renderizzati nel browser.
tags:
  - 'Architectuur en API’s'
image: 'https://dxpr.com/themes/custom/dxpr_com/images/dxpr-share-card.jpg'
published: true
og:
  site_name: DXPR
  updated_time: '2026-10-24T09:09:48+0000'
  'image:alt': 'DXPR, powered by Drupal: AI-powered Drupal for marketers.'
schema:
  '@context': 'https://schema.org'
  '@graph':
    -
      mainEntity: {  }
    -
      '@type': TechArticle
      headline: 'Creare elementi personalizzati'
      description: |-
        Ogni elemento di DXPR Builder è un oggetto JavaScript inserito in
        window.dxprBuilder.dxpr_elements. L’editor trasforma ogni oggetto
        in una classe di elemento con le schede Style e Animation già
        collegate. Questa pagina mostra come sono definiti gli elementi inclusi in
        dxpr_builder/dxpr_elements.js, come un modulo aggiunge la sua
        definizione all’editor e come appare l’HTML risultante.
        Non esistono modelli Twig lato server per elemento; gli elementi
        sono renderizzati nel browser.
      image:
        '@type': ImageObject
        url: 'https://dxpr.com/themes/custom/dxpr_com/images/dxpr-share-card.jpg'
        width: '1200'
        height: '630'
      datePublished: '2026-10-24T03:04:16+0000'
      dateModified: '2026-10-24T09:09:48+0000'
      author:
        '@type': Organization
        '@id': 'https://dxpr.com/#organization'
        name: DXPR
        url: 'https://dxpr.com/'
        logo:
          '@type': ImageObject
          url: 'https://dxpr.com/themes/custom/dxpr_com/dxpr-logo-dark.svg'
          width: '1348'
          height: '501'
      publisher:
        '@type': Organization
        '@id': 'https://dxpr.com/#organization'
        name: DXPR
        url: 'https://dxpr.com/'
        logo:
          '@type': ImageObject
          url: 'https://dxpr.com/themes/custom/dxpr_com/dxpr-logo-dark.svg'
          width: '1348'
          height: '501'
      mainEntityOfPage: 'https://dxpr.com/it/hc/documentation/learn-dxpr-builder/development/custom-elements'
      articleSection: 'Architectuur en API’s'
    -
      '@type': WebPage
      '@id': 'https://dxpr.com/it/hc/documentation/learn-dxpr-builder/development/custom-elements'
      description: |-
        Ogni elemento di DXPR Builder è un oggetto JavaScript inserito in
        window.dxprBuilder.dxpr_elements. L’editor trasforma ogni oggetto
        in una classe di elemento con le schede Style e Animation già
        collegate. Questa pagina mostra come sono definiti gli elementi inclusi in
        dxpr_builder/dxpr_elements.js, come un modulo aggiunge la sua
        definizione all’editor e come appare l’HTML risultante.
        Non esistono modelli Twig lato server per elemento; gli elementi
        sono renderizzati nel browser.
      breadcrumb:
        '@type': BreadcrumbList
        itemListElement:
          -
            '@type': ListItem
            position: 1
            name: Home
            item: 'https://dxpr.com/it'
      publisher:
        '@type': Organization
        '@id': 'https://dxpr.com/#organization'
        name: DXPR
      inLanguage: it
---
[Help Center](/it/hc)/[Documentation](/it/hc/documentation) /[Learn DXPR Builder](/hc/documentation/learn-dxpr-builder) /[Extend](/hc/documentation/learn-dxpr-builder/extend) /[Architectuur en API’s](/hc/documentation/learn-dxpr-builder/extend/architecture) # Creare elementi personalizzati.

 Learn DXPR BuilderExtendArchitectuur en API’s

   ## In this guide

 Related guides

- [Riferimento API hook](/it/hc/documentation/learn-dxpr-builder/development/hooks-api)
- [Architettura](/it/hc/documentation/learn-dxpr-builder/development/architecture)

Ogni elemento di DXPR Builder è un oggetto JavaScript inserito in `window.dxprBuilder.dxpr_elements`. L’editor trasforma ogni oggetto in una classe di elemento con le schede Style e Animation già collegate. Questa pagina mostra come sono definiti gli elementi inclusi in `dxpr_builder/dxpr_elements.js`, come un modulo aggiunge la sua definizione all’editor e come appare l’HTML risultante. Non esistono modelli Twig lato server per elemento; gli elementi sono renderizzati nel browser.

## Come l’editor registra gli elementi

L’editor carica sei script in quest’ordine, definiti in `dxpr_builder_library_info_build()` in `dxpr_builder.module` come libreria `dxpr_builder/editor.builder`:

1. `dxpr_templates.js`: modelli twig.js lato client compilati da `dxpr_builder/templates/`.
2. `dxpr_global.js`: helper condivisi e integrazione CKEditor 5.
3. `dxpr_events.js`
4. `dxpr_param_types.js`: inserisce un oggetto per tipo di input in `window.dxprBuilder.dxpr_param_types`.
5. `dxpr_elements.js`: crea l’array `window.dxprBuilder.dxpr_elements`e inserisce una definizione per elemento.
6. `dxpr_builder.js`: l’editor. Quando questo file è eseguito chiama `create_dxpr_elements()`, che cicla su `window.dxprBuilder.dxpr_elements` e per ogni definizione:
    - chiama `register_animated_element(base, is_container, Class)`, così la classe estende `AnimatedElement` (scheda Style, scheda Animation, HTML ID, HTML classes e parametri di posizionamento);
    - accoda i parametri ereditati ai `params` della definizione;
    - converte ogni parametro tramite `make_param_type()`, che confronta `param.type` con i tipi di parametro registrati;
    - mescola le proprietà della definizione nel prototipo della classe.

Una definizione deve quindi stare sull’array dopo che `dxpr_elements.js` è girato e prima che `dxpr_builder.js` giri. Tutti e sei i file si caricano con l’attributo `defer`, quindi l’ordine dei tag script nel documento è l’ordine di esecuzione.

## La definizione di elemento

Questo è l’elemento Alert da `dxpr_builder/dxpr_elements.js`(sorgente: `dxpr_builder/build/dxpr-elements/elements/az_alert.js`), ridotto alle proprietà necessarie a ogni elemento. L’originale imposta anche `el_class`, un handler `onCancel` e un listener `focusout`.

```javascript
window.dxprBuilder.dxpr_elements.push({
  base: "az_alert",
  name: Drupal.t("Alert"),
  nameEn: "Alert",
  icon: "az-custom-icon az-alert-icon",
  largeSettingsWindow: true,
  hidden: false,
  params: [
    {
      type: "textarea",
      heading: Drupal.t("Message"),
      param_name: "content",
      value: Drupal.t(
        "This is a placeholder text. Your actual content will go here. Edit this to include your own information.",
      ),
    },
    {
      type: "dropdown",
      heading: Drupal.t("Type"),
      param_name: "type",
      description: Drupal.t("Select message type."),
      getText: (opt) => opt.text,
      getValue: (opt) => opt.value,
      getDefault: (param) => param.value["alert-success"].value,
      value: {
        "alert-success": { text: Drupal.t("Success"), value: "alert-success" },
        "alert-info": { text: Drupal.t("Info"), value: "alert-info" },
        "alert-warning": { text: Drupal.t("Warning"), value: "alert-warning" },
        "alert-danger": { text: Drupal.t("Danger"), value: "alert-danger" },
      },
      passthrough: true,
    },
  ],
  show_settings_on_create: true,
  has_content: true,
  render(...args) {
    const state = {
      class: `az-element az-alert alert ${this.attrs.type} ${this.get_el_classes()} ${this.get_content_classes()}`,
      style: this.attrs.style,
      message: this.attrs.content,
    };
    this.dom_element = this.baseclass.prototype.render_template(
      "elements/alert/alert",
      state,
    );
    this.baseclass.prototype.render.apply(this, args);
  },
  save_history() {
    const container = this.get_my_container();
    container.save_container_history(Drupal.t("Edit alert"));
  },
});

```

| Proprietà | Scopo |
|---|---|
| `base` | Nome macchina. È scritto nell’HTML salvato come `data-azb="az_alert"` ed è usato per trovare la classe quando la pagina è analizzata di nuovo. Mantieni il prefisso `az_`. |
| `name`, `nameEn` | Etichetta nel selettore di elementi e sua forma non tradotta. |
| `icon` | Classi CSS per l’icona del selettore. Le icone incluse sono definite in `dxpr_builder/sass/dxpr-builder-backend/components/_custom-icons.scss`; un elemento personalizzato richiede il proprio CSS per la sua classe icona. |
| `category` | Scheda del selettore. Gli elementi di layout usano `Drupal.t("Layout")`; blocchi e viste usano `"CMS"`. Omettila per la scheda di contenuto predefinita. |
| `is_container` | `true` quando l’elemento contiene altri elementi. |
| `largeSettingsWindow` | Apre la finestra delle impostazioni nella dimensione maggiore. |
| `hidden` | Nasconde l’elemento dal selettore mantenendolo renderizzabile. |
| `params` | Impostazioni mostrate nella finestra. Vedi sotto. |
| `show_settings_on_create` | Apre la finestra delle impostazioni appena l’elemento è rilasciato. |
| `has_content` | L’elemento ha un’area di contenuto modificabile (`dom_content_element`). |
| `render(...args)` | Costruisce `this.dom_element` da `this.attrs`, poi chiama il `render` base. |
| `save_history()` | Inserisce una voce di annullamento con un’etichetta. |
| `parse_attrs_from_dom(element)` | Opzionale. Rilegge i valori dei parametri dal markup salvato, usato insieme a `skip_data_azb` e `skip_params` da elementi come Image che memorizzano i valori negli attributi `<img>` invece che in `data-azat-*`. |

### Parametri

Ogni voce in `params` ha:

| Chiave | Significato |
|---|---|
| `type` | Uno dei tipi di parametro registrati (sezione successiva). |
| `heading` | Etichetta del campo. |
| `param_name` | Chiave in `this.attrs` e, nell’HTML salvato, l’attributo `data-azat-<param_name>`. `content` è speciale: è il corpo dell’elemento, non un attributo. |
| `value` | Valore predefinito. Per `dropdown` è un oggetto di opzioni con callback `getText`, `getValue` e `getDefault`. |
| `description` | Testo di aiuto sotto il campo. |
| `tab` | Raggruppa il campo in un accordion con nome, ad esempio `Drupal.t("SEO")`. |
| `can_be_empty` | Memorizza una stringa vuota invece di rimuovere l’attributo. |
| `safe` | Salta la codifica URL del valore memorizzato. |

I tipi di parametro sono i valori `type` inseriti in `window.dxprBuilder.dxpr_param_types` in `dxpr_builder/dxpr_param_types.js`: `boxmodel`, `checkbox`, `checkboxes`, `colorpicker`, `datetime`, `dropdown`, `dxb_slider`, `html`, `icon`, `image`, `images`, `link`, `links`, `numericfield`, `row_layout`, `saved_datetime`, `social_links`, `textarea`, `textfield` e `video`. Un tipo non registrato ripiega a un semplice input di testo (`BaseParamType`).

Non riutilizzare un `param_name` ereditato da ogni elemento, come `color`, `background`, `el_class`, `hash` o i nomi di animazione `an_*`. La scheda Style possiede già `color`, quindi un secondo parametro con quel nome non è mai scritto in `data-azat-color`.

### Cosa viene salvato

`update_data()` in `dxpr_builder.js` scrive l’elemento in HTML:

- `data-azb="<base>"` sull’elemento root;
- `data-azat-<param_name>="<value>"` per ogni parametro il cui valore differisce dal predefinito, codificato URL a meno che il parametro imposti `safe: true`;
- i parametri della scheda Style come `style` inline e classi, mai come attributi `data-azat-*`;
- `data-azcnt="true"` sull’elemento di contenuto quando `has_content` è impostato.

I visitatori senza editor ricevono questo HTML senza i suoi attributi `data-az*`: `DxprBuilderService::parseDocumentForCleanup()`li rimuove, tranne un elenco fisso mantenuto sugli elementi animati e sugli elementi dinamici integrati come Carousel. Se l’elemento richiede JavaScript o CSS per i visitatori, metti un attributo `data-dxpr-builder-libraries="<key>"` sulla sua root: `parseDocumentForTemplateLibrary()` collega `dxpr_builder/elements.<key>` per ogni chiave senza slash. Le chiavi sono le librerie `elements.*` in `dxpr_builder.libraries.yml`; una chiave con slash è onorata solo quando è la `library` di un set di icone registrato.

## Esempio minimo funzionante

L’esempio aggiunge un elemento "Notice" che renderizza un paragrafo con un colore scelto. Costruisce il suo DOM direttamente perché i modelli twig.js compilati in `dxpr_templates.js` fanno parte del bundle dell’editor e non possono essere estesi da un altro modulo.

1. Crea `mymodule/js/notice-element.js`:

    ```javascript
    window.dxprBuilder.dxpr_elements.push({
      base: "az_notice",
      name: Drupal.t("Notice"),
      nameEn: "Notice",
      icon: "az-custom-icon az-alert-icon",
      params: [
        {
          type: "textfield",
          heading: Drupal.t("Text"),
          param_name: "text",
          value: Drupal.t("Notice text"),
        },
        {
          type: "colorpicker",
          heading: Drupal.t("Colour"),
          param_name: "notice_color",
          value: "#0d6efd",
        },
      ],
      show_settings_on_create: true,
      render(...args) {
        const el = document.createElement("div");
        el.className = `az-element az-notice ${this.get_el_classes()}`;
        if (this.attrs.style) {
          el.setAttribute("style", this.attrs.style);
        }
        const p = document.createElement("p");
        p.style.color = this.attrs.notice_color;
        p.textContent = this.attrs.text;
        el.appendChild(p);
        this.dom_element = el;
        this.baseclass.prototype.render.apply(this, args);
      },
      save_history() {
        this.get_my_container().save_container_history(Drupal.t("Edit notice"));
      },
    });

    ```
2. Inserisci il file nella libreria dell’editor tra `dxpr_elements.js` (peso `-4`) e `dxpr_builder.js` (peso `-3`) in `mymodule.module`:

    ```php
    /**
     * Implements hook_library_info_alter().
     */
    function mymodule_library_info_alter(array &$libraries, string $extension): void {
      if ($extension === 'dxpr_builder' && isset($libraries['editor.builder'])) {
        $path = '/' . \Drupal::service('extension.list.module')->getPath('mymodule');
        $libraries['editor.builder']['js'][$path . '/js/notice-element.js'] = [
          'weight' => -3.5,
          'preprocess' => FALSE,
          'attributes' => ['defer' => TRUE],
        ];
      }
    }

    ```

    `preprocess: FALSE` e `defer` corrispondono alle voci che il modulo definisce per i suoi file, così il file mantiene il suo posto nella sequenza sia che gli asset dell’editor vengano dalla CDN o da una build locale.
3. Svuota la cache e apri una pagina builder:

    ```bash
    drush cr

    ```
4. Aggiungi l’elemento dal selettore, impostane testo e colore, e salva. Il campo memorizza:

    ```html
    <div class="az-element az-notice" id="..." data-azb="az_notice"
         data-azat-text="Hello" data-azat-notice_color="%23198754">
      <p style="color: #198754;">Hello</p>
    </div>

    ```

    Un visitatore riceve lo stesso markup senza gli attributi `data-az*`. Il paragrafo mantiene il suo colore inline, quindi nessuna libreria per visitatori serve per questo elemento.

## Limiti da conoscere

- **I profili non elencano elementi personalizzati.** La checklist degli elementi in un profilo builder viene da un elenco fisso in `src/Form/DxprBuilderProfileForm.php` e `src/Service/Handler/ProfileHandler.php`. Gli elementi fuori da quell’elenco non sono mai nascosti da un profilo.
- **Le icone per il selettore** richiedono CSS dal tuo modulo; le classi `az-custom-icon` incluse nel builder coprono solo gli elementi inclusi.
- **`DxprBuilderService::getDxprElementsFolders()`** e il suo `hook_dxpr_builder_elements_folders_alter()` restituiscono un elenco di cartelle `elements` nei temi, ma niente nell’editor legge quell’elenco. Non è una route di registrazione.
- **Le schede Style e Animation** sono aggiunte per te da `register_animated_element()`; non ridefinire quei parametri.

## Prossimi passi

- [Riferimento API hook](/it/hc/documentation/learn-dxpr-builder/development/hooks-api) per gli hook PHP che aggiungono classi di utilità e set di icone.
- [Architettura](/it/hc/documentation/learn-dxpr-builder/development/architecture) per come l’editor e il formatter di campo stanno insieme.