[comment]: # aside:2

[comment]: # ({49595c0a-680e771f})
# Presentazione

Questa pagina descrive i componenti che possono essere utilizzati per creare una vista di presentazione del widget.
La vista di presentazione del widget è la parte del widget che riceve i dati in base alla sua [configurazione](/configuration) e li visualizza sulla dashboard in un contenitore.

La vista di presentazione è composta da tre parti:

-   [Azione del widget](#widget-action)
-   [Vista del widget](#widget-view)
-   [JavaScript](#javascript)

[comment]: # ({/49595c0a-680e771f})

[comment]: # ({12d91455-59d8ff17})
### Azione del widget

La classe di azione del widget (*WidgetView*) contiene metodi per le operazioni con i widget nella modalità di visualizzazione della presentazione.
La maggior parte delle azioni dei widget utilizza e/o estende la classe controller predefinita *CControllerDashboardWidgetView*.

La classe di azione del widget deve trovarsi nella directory *actions* ed essere specificata nel parametro [*actions*](/devel/modules/file_structure/manifest#actions) (*actions/widget.{id}.view/class*) nel file *manifest.json*.

**Esempio di actions/WidgetView.php (implementato nel widget nativo di Zabbix [*Informazioni di sistema*](/manual/web_interface/frontend_sections/dashboards/widgets/system))**

```php
class WidgetView extends CControllerDashboardWidgetView {

    protected function doAction(): void {
        $this->setResponse(new CControllerResponseData([
            'name' => $this->getInput('name', $this->widget->getDefaultName()),
            'system_info' => CSystemInfoHelper::getData(),
            'info_type' => $this->fields_values['info_type'],
            'user_type' => CWebUser::getType(),
            'user' => [
                'debug_mode' => $this->getDebugMode()
            ]
        ]));
    }
}
```

[comment]: # ({/12d91455-59d8ff17})

[comment]: # ({c06252a9-962bf489})
### Vista del widget

La classe della vista del widget (*CWidgetView*) è responsabile della costruzione della vista di presentazione del widget.

La classe della vista del widget deve trovarsi nella directory *views*.
Se il file che contiene la classe della vista del widget ha un nome diverso da quello predefinito (*widget.view.php*), allora deve essere specificato nel file *manifest.json* nel parametro [*actions*](/devel/modules/file_structure/manifest#actions) (*actions/widget.{id}.view/view*).

**Esempio di views/widget.view.php**

```php
<?php

/**
 * My custom widget view.
 *
 * @var CView $this
 * @var array $data
 */

(new CWidgetView($data))
    ->addItem(
        new CTag('h1', true, $data['name'])
    )
    ->show();
```

[comment]: # ({/c06252a9-962bf489})

[comment]: # ({f4f943a3-9c902f1e})
### JavaScript

La classe JavaScript è responsabile della definizione del comportamento del widget, ad esempio l'aggiornamento dei dati del widget, il ridimensionamento del widget, la visualizzazione degli elementi del widget, ecc.

Tutte le operazioni JavaScript utilizzano e/o estendono la classe JavaScript di base di tutti i widget della dashboard - *CWidget*.
La classe *CWidget* contiene un insieme di metodi con l'implementazione predefinita del comportamento del widget.
A seconda della complessità del widget, questi metodi possono essere utilizzati così come sono oppure estesi.

La classe *CWidget* contiene i seguenti metodi:

-   Metodi che definiscono il ciclo di vita del widget: *onInitialize()*, *onStart()*, *onActivate()*, *onDeactivate()*, *onDestroy()*, *onEdit()*.
-   Metodi che gestiscono l'aggiornamento e la visualizzazione dei dati del widget: *promiseUpdate()*, *getUpdateRequestData()*, *processUpdateResponse(response)*, *processUpdateErrorResponse(error)*, *setContents(response)*.
-   Metodi che modificano l'aspetto del widget: *onResize()*, *hasPadding()*.

La classe JavaScript deve trovarsi nella directory *assets/js* ed essere specificata nel parametro [*assets*](/devel/modules/file_structure/manifest#assets) (*assets/js*) nel file *manifest.json*.

[comment]: # ({/f4f943a3-9c902f1e})

[comment]: # ({83b2097c-be08c6bd})
##### Metodi del ciclo di vita

I metodi del ciclo di vita del widget vengono invocati dalla dashboard, e in diverse fasi del ciclo di vita del widget durante la sua esistenza all'interno della dashboard.

[comment]: # ({/83b2097c-be08c6bd})

[comment]: # ({af2ec67e-bbc2c368})
Il metodo ***onInitialize()*** definisce lo stato iniziale e/o i valori del widget, senza eseguire alcuna manipolazione di HTML o dei dati.
Questo metodo viene richiamato quando un widget viene creato (viene istanziato un oggetto widget), in genere aggiungendo il widget a una pagina della dashboard o caricando la pagina della dashboard.

Esempio:

```js
onInitialize() {
    this._time_offset = 0;
    this._interval_id = null;
    this._clock_type = CWidgetClock.TYPE_ANALOG;
    this._time_zone = null;
    this._show_seconds = true;
    this._time_format = 0;
    this._tzone_format = 0;
    this._show = [];
    this._has_contents = false;
    this._is_enabled = true;
}
```

[comment]: # ({/af2ec67e-bbc2c368})

[comment]: # ({d89d02f3-9d16c8d2})
Il metodo ***onStart()*** definisce la struttura HTML del widget, senza eseguire alcuna manipolazione dei dati.
Questo metodo viene invocato prima della prima attivazione della pagina della dashboard, cioè prima che la dashboard e i relativi widget siano completamente visualizzati all'utente.

Esempio:

```js
onStart() {
    this._events.resize = () => {
        const padding = 25;
        const header_height = this._view_mode === ZBX_WIDGET_VIEW_MODE_HIDDEN_HEADER
            ? 0
            : this._header.offsetHeight;

        this._target.style.setProperty(
            '--content-height',
            `${this._cell_height * this._pos.height - padding * 2 - header_height}px`
        );
    }
}
```

[comment]: # ({/d89d02f3-9d16c8d2})

[comment]: # ({02fa6174-eb9b91db})
Il metodo ***onActivate()*** rende il widget attivo e interattivo abilitando listener di eventi personalizzati (per rispondere alle azioni dell'utente) e avviando il ciclo di aggiornamento del widget (per mantenere il suo contenuto aggiornato).
Questo metodo viene richiamato quando la pagina della dashboard viene attivata, cioè quando viene visualizzata completamente nell'interfaccia utente.

Si noti che prima che il metodo *onActivate()* venga richiamato, il widget si trova nello stato inattivo (`WIDGET_STATE_INACTIVE`).
Dopo il richiamo riuscito, il widget passa allo stato attivo (`WIDGET_STATE_ACTIVE`).
Nello stato attivo, il widget è reattivo, ascolta gli eventi, aggiorna periodicamente il proprio contenuto e può interagire con altri widget.

Esempio:

```js
onActivate() {
    this._startClock();

    this._resize_observer = new ResizeObserver(this._events.resize);
    this._resize_observer.observe(this._target);
}
```

[comment]: # ({/02fa6174-eb9b91db})

[comment]: # ({4464acae-1b9abef7})
Il metodo ***onDeactivate()*** interrompe qualsiasi attività e interattività del widget disattivando i listener di eventi personalizzati e arrestando il ciclo di aggiornamento del widget.
Questo metodo viene richiamato quando la pagina della dashboard viene disattivata, cioè quando si passa a un'altra pagina o viene eliminata, oppure quando il widget viene eliminato dalla pagina della dashboard.

Si noti che prima che il metodo *onDeactivate()* venga richiamato, il widget si trova nello stato attivo (`WIDGET_STATE_ACTIVE`).
Dopo il richiamo riuscito, il widget passa allo stato inattivo (`WIDGET_STATE_INACTIVE`).

Esempio:

```js
onDeactivate() {
    this._stopClock();
    this._resize_observer.disconnect();
}
```

[comment]: # ({/4464acae-1b9abef7})

[comment]: # ({a26add25-06e3db00})
Il metodo ***onDestroy()*** esegue le operazioni di pulizia prima che il widget venga eliminato dalla dashboard,
che possono includere la chiusura di una connessione al database stabilita durante l'inizializzazione del widget,
la rimozione dei dati temporanei per liberare memoria di sistema ed evitare perdite di risorse,
la deregistrazione degli event listener relativi agli eventi di ridimensionamento o ai clic sui pulsanti per prevenire la gestione non necessaria degli eventi e perdite di memoria, ecc.
Questo metodo viene richiamato quando il widget o la pagina della dashboard che lo contiene viene eliminata.

Si noti che prima che il metodo *onDestroy()* venga richiamato, un widget in stato attivo (`WIDGET_STATE_ACTIVE`) viene sempre disattivato tramite il richiamo del metodo *onDeactivate()*.

Esempio:

```js
onDestroy() {
    if (this._filter_widget) {
        this._filter_widget.off(CWidgetMap.WIDGET_NAVTREE_EVENT_MARK, this._events.mark);
        this._filter_widget.off(CWidgetMap.WIDGET_NAVTREE_EVENT_SELECT, this._events.select);
    }
}
```

[comment]: # ({/a26add25-06e3db00})

[comment]: # ({b38c4c19-5e5aaf59})
Il metodo ***onEdit()*** definisce l'aspetto e il comportamento del widget quando la dashboard passa alla modalità di modifica.
Questo metodo viene richiamato quando la dashboard passa alla modalità di modifica, in genere quando un utente interagisce con il pulsante *Edit* del widget o con il pulsante *Edit dashboard* della dashboard.

Esempio:

```js
onEdit() {
    this._deactivateGraph();
}
```

[comment]: # ({/b38c4c19-5e5aaf59})

[comment]: # ({1e54f2e8-87f28aae})
##### Metodi del processo di aggiornamento

I metodi del processo di aggiornamento del widget sono responsabili del recupero dei dati aggiornati dal server Zabbix o da qualsiasi altra origine dati e della loro visualizzazione nel widget.

[comment]: # ({/1e54f2e8-87f28aae})

[comment]: # ({fa94eb63-c743ab46})
Il metodo ***promiseUpdate()*** avvia il processo di aggiornamento dei dati recuperandoli, in genere tramite richieste web o chiamate API.
Questo metodo viene richiamato quando viene visualizzata una pagina della dashboard e successivamente a intervalli periodici, finché la pagina della dashboard non viene cambiata con un'altra pagina della dashboard.

Di seguito è riportato un esempio dell'implementazione predefinita del metodo *promiseUpdate()* utilizzata dalla maggior parte dei widget nativi di Zabbix.
Nell'implementazione predefinita, il metodo *promiseUpdate()* segue uno schema generale per il recupero dei dati dal server.
Crea un nuovo oggetto `Curl` con l'URL appropriato e i parametri della richiesta,
invia una richiesta `POST` usando il metodo *fetch()* con l'oggetto dati costruito dal metodo *getUpdateRequestData()*,
ed elabora la risposta (o una risposta di errore) rispettivamente con *processUpdateResponse(response)* o *processUpdateErrorResponse(error)*.
Questa implementazione è adatta alla maggior parte dei widget, poiché in genere recuperano i dati in formato JSON e li gestiscono in modo coerente.

```js
promiseUpdate() {
    const curl = new Curl('zabbix.php');

    curl.setArgument('action', `widget.${this._type}.view`);

    return fetch(curl.getUrl(), {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(this.getUpdateRequestData()),
        signal: this._update_abort_controller.signal
    })
        .then((response) => response.json())
        .then((response) => {
            if ('error' in response) {
                this.processUpdateErrorResponse(response.error);

                return;
            }

            this.processUpdateResponse(response);
        });
    }
```

[comment]: # ({/fa94eb63-c743ab46})

[comment]: # ({5d0423d9-5b7f40bf})
Il metodo ***getUpdateRequestData()*** prepara i dati della richiesta al server per l'aggiornamento del widget raccogliendo varie proprietà e i relativi valori (identificatori del widget, impostazioni dei filtri, intervalli di tempo, ecc.) dallo stato e dalla configurazione del widget,
e costruendo un oggetto dati che rappresenta le informazioni necessarie da inviare al server nella richiesta di aggiornamento.
Questo metodo viene richiamato solo come parte del metodo predefinito *promiseUpdate()*, cioè durante il processo di aggiornamento del widget.

Implementazione predefinita:

```js
getUpdateRequestData() {
    return {
        templateid: this._dashboard.templateid ?? undefined,
        dashboardid: this._dashboard.dashboardid ?? undefined,
        widgetid: this._widgetid ?? undefined,
        name: this._name !== '' ? this._name : undefined,
        fields: Object.keys(this._fields).length > 0 ? this._fields : undefined,
        view_mode: this._view_mode,
        edit_mode: this._is_edit_mode ? 1 : 0,
        dynamic_hostid: this._dashboard.templateid !== null || this.supportsDynamicHosts()
            ? (this._dynamic_hostid ?? undefined)
            : undefined,
        ...this._contents_size
    };
}
```

[comment]: # ({/5d0423d9-5b7f40bf})

[comment]: # ({980ceee3-dd2550e1})
Il metodo ***processUpdateResponse(response)*** gestisce la risposta ricevuta dal server dopo la richiesta di aggiornamento e, se il processo di aggiornamento è andato a buon fine e senza errori, svuota i dati del widget e visualizza i nuovi contenuti con il metodo *setContents()*.
Questo metodo viene richiamato solo come parte del metodo predefinito *promiseUpdate()*, cioè durante il processo di aggiornamento del widget.

Implementazione predefinita:

```js
processUpdateResponse(response) {
    this._setHeaderName(response.name);

    this._updateMessages(response.messages);
    this._updateInfo(response.info);
    this._updateDebug(response.debug);

    this.setContents(response);
}
```

[comment]: # ({/980ceee3-dd2550e1})

[comment]: # ({d3ce9166-2abd3964})
Il metodo ***processUpdateErrorResponse(error)*** gestisce la risposta ricevuta dal server dopo la richiesta di aggiornamento se la risposta è un errore e visualizza il/i messaggio/i di errore.
Questo metodo viene richiamato solo come parte del metodo predefinito *promiseUpdate()*, cioè durante il processo di aggiornamento del widget.

Implementazione predefinita:

```js
processUpdateErrorResponse(error) {
    this._updateMessages(error.messages, error.title);
}
```

[comment]: # ({/d3ce9166-2abd3964})

[comment]: # ({31ffc8a7-8ea0452d})
Il metodo ***setContents(response)*** visualizza il contenuto del widget se il processo di aggiornamento del widget è stato completato con successo e senza errori,
il che può includere la manipolazione di elementi DOM, l'aggiornamento di componenti dell'interfaccia utente, l'applicazione di stili o formattazione, ecc.
Questo metodo viene richiamato solo come parte del metodo predefinito *processUpdateResponse(response)*, cioè durante il processo di gestione della risposta ricevuta dal server dopo la richiesta di aggiornamento.

Implementazione predefinita:

```js
setContents(response) {
    this._body.innerHTML = response.body ?? '';
}
```

[comment]: # ({/31ffc8a7-8ea0452d})

[comment]: # ({7b8ba0e6-95f750ef})
##### Metodi di modifica della presentazione

I metodi di modifica della presentazione del widget sono responsabili della modifica dell'aspetto del widget.

[comment]: # ({/7b8ba0e6-95f750ef})

[comment]: # ({5e245dd6-b5613994})
Il metodo ***onResize()*** è responsabile dell'adattamento degli elementi visivi del widget per adeguarsi alle nuove dimensioni del widget,
operazione che può includere la riorganizzazione degli elementi, la regolazione delle dimensioni degli elementi, il troncamento del testo, l'implementazione del lazy loading per migliorare la reattività durante il ridimensionamento, ecc.
Questo metodo viene richiamato quando il widget viene ridimensionato, ad esempio quando l'utente ridimensiona manualmente il widget o quando viene ridimensionata la finestra del browser.

Esempio:

```js
onResize() {
    if (this.getState() === WIDGET_STATE_ACTIVE) {
        this._startUpdating();
    }
}
```

[comment]: # ({/5e245dd6-b5613994})

[comment]: # ({d22bedba-88b32413})
Il metodo ***hasPadding()*** è responsabile dell'applicazione di un padding verticale di 8 px nella parte inferiore del widget quando è configurato per [mostrare la propria intestazione](/manual/web_interface/frontend_sections/dashboards/widgets#common-parameters).
Questo metodo viene richiamato quando la pagina della dashboard viene attivata, cioè quando diventa la pagina visualizzata nell'interfaccia utente.

Implementazione predefinita:

```js
hasPadding() {
    return this.getViewMode() !== ZBX_WIDGET_VIEW_MODE_HIDDEN_HEADER;
}
```

Per alcuni widget è necessario utilizzare tutto lo spazio disponibile del widget per configurare, ad esempio, un colore di sfondo personalizzato.
Di seguito è riportato un esempio dell'implementazione del metodo *hasPadding()* utilizzato nel widget [*Item value*](/manual/web_interface/frontend_sections/dashboards/widgets/item_value) nativo di Zabbix.

```js
hasPadding() {
    return false;
}
```

[comment]: # ({/d22bedba-88b32413})
