[comment]: # aside:2

[comment]: # ({49595c0a-680e771f})
# Präsentation

Diese Seite beschreibt die Komponenten, die zur Erstellung einer Widget-Präsentationsansicht verwendet werden können.
Die Widget-Präsentationsansicht ist der Teil des Widgets, der die Daten gemäß seiner [Konfiguration](/configuration) empfängt und sie auf dem Dashboard in einem Container anzeigt.

Die Präsentationsansicht besteht aus drei Teilen:

-   [Widget-Aktion](#widget-action)
-   [Widget-Ansicht](#widget-view)
-   [JavaScript](#javascript)

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

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

Die Widget-Aktionsklasse (*WidgetView*) enthält Methoden für Operationen mit Widgets im Präsentationsansichtsmodus. 
Die meisten Widget-Aktionen verwenden und/oder erweitern die Standard-Controllerklasse *CControllerDashboardWidgetView*.

Die Widget-Aktionsklasse sollte sich im Verzeichnis *actions* befinden und im Parameter [*actions*](/devel/modules/file_structure/manifest#actions) (*actions/widget.{id}.view/class*) in der Datei *manifest.json* angegeben sein.

**actions/WidgetView.php Beispiel (implementiert im Zabbix-eigenen [*Systeminformationen*](/manual/web_interface/frontend_sections/dashboards/widgets/system) widget)**

```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})
### Widget-Ansicht

Die Widget-Ansichtsklasse (*CWidgetView*) ist für den Aufbau der Widget-Darstellungsansicht verantwortlich.  

Die Widget-Ansichtsklasse sollte sich im *views*-Verzeichnis befinden.  
Wenn die Datei, die die Widget-Ansichtsklasse enthält, einen anderen Namen als den Standardnamen (*widget.view.php*) hat, muss sie im *manifest.json*-Datei-[*actions*](/devel/modules/file_structure/manifest#actions)-Parameter (*actions/widget.{id}.view/view*) angegeben werden.

**views/widget.view.php Beispiel**

```php
<?php

/**
 * Meine benutzerdefinierte Widget-Ansicht.
 *
 * @var CView $this
 * @var array $data
 */

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

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

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

Die JavaScript-Klasse ist für das Verhalten des Widgets verantwortlich, wie das Aktualisieren von Widget-Daten, das Anpassen der Größe des Widgets, das Anzeigen von Widget-Elementen usw.

Alle JavaScript-Operationen verwenden und/oder erweitern die JavaScript-Basisklasse für alle Dashboard-Widgets - *CWidget*.  
Die *CWidget*-Klasse enthält eine Reihe von Methoden mit der Standardimplementierung für das Widget-Verhalten.  
Abhängig von der Komplexität des Widgets können diese Methoden so verwendet oder erweitert werden.

Die *CWidget*-Klasse enthält die folgenden Methoden:

-   Methoden, die den Lebenszyklus eines Widgets definieren: *onInitialize()*, *onStart()*, *onActivate()*, *onDeactivate()*, *onDestroy()*, *onEdit()*.
-   Methoden, die das Aktualisieren und Anzeigen von Widget-Daten steuern: *promiseUpdate()*, *getUpdateRequestData()*, *processUpdateResponse(response)*, *processUpdateErrorResponse(error)*, *setContents(response)*.
-   Methoden, die das Aussehen des Widgets anpassen: *onResize()*, *hasPadding()*.

Die JavaScript-Klasse sollte sich im Verzeichnis *assets/js* befinden und im [*assets*](/devel/modules/file_structure/manifest#assets)-Parameter (*assets/js*) in der *manifest.json*-Datei angegeben werden.

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

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

Die Lebenszyklusmethoden des Widgets werden vom Dashboard und in verschiedenen Stadien des Lebenszyklus des Widgets während seiner Existenz im Dashboard aufgerufen.

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

[comment]: # ({af2ec67e-bbc2c368})
Die Methode ***onInitialize()*** definiert den anfänglichen Zustand und/oder die Werte des Widgets, ohne HTML- oder Datenmanipulationen durchzuführen.  
Diese Methode wird aufgerufen, wenn ein Widget erstellt wird (ein Widget-Objekt instanziiert wird), typischerweise durch das Hinzufügen des Widgets zu einer Dashboard-Seite oder durch das Laden der Dashboard-Seite.

Beispiel:

```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})
Die Methode ***onStart()*** definiert die HTML-Struktur des Widgets, ohne dabei Daten zu verarbeiten.
Diese Methode wird vor der ersten Aktivierung der Dashboard-Seite aufgerufen, also bevor das Dashboard und seine Widgets dem Benutzer vollständig angezeigt werden.

Beispiel:

```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})
Die Methode ***onActivate()*** macht das Widget aktiv und interaktiv, indem sie benutzerdefinierte Event-Listener aktiviert (um auf Benutzeraktionen zu reagieren) und den Aktualisierungszyklus des Widgets startet (um seinen Inhalt auf dem neuesten Stand zu halten).
Diese Methode wird aufgerufen, wenn die Dashboard-Seite aktiviert wird, das heißt, wenn sie in der Benutzeroberfläche vollständig angezeigt wird.

Beachten Sie, dass sich das Widget vor dem Aufruf der Methode *onActivate()* im inaktiven Zustand (`WIDGET_STATE_INACTIVE`) befindet.
Nach erfolgreichem Aufruf wechselt das Widget in den aktiven Zustand (`WIDGET_STATE_ACTIVE`).
Im aktiven Zustand reagiert das Widget, lauscht auf Ereignisse, aktualisiert seinen Inhalt periodisch und kann mit anderen Widgets interagieren.

Beispiel:

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

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

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

[comment]: # ({4464acae-1b9abef7})
Die Methode ***onDeactivate()*** beendet jede Aktivität und Interaktivität des Widgets, indem benutzerdefinierte Event-Listener deaktiviert und der Aktualisierungszyklus des Widgets gestoppt werden.
Diese Methode wird aufgerufen, wenn die Dashboard-Seite deaktiviert wird, d. h. wenn zu einer anderen Seite gewechselt wird oder sie gelöscht wird, oder wenn das Widget von der Dashboard-Seite gelöscht wird.

Beachten Sie, dass sich das Widget vor dem Aufruf der Methode *onDeactivate()* im aktiven Zustand (`WIDGET_STATE_ACTIVE`) befindet.
Nach erfolgreichem Aufruf wechselt das Widget in den inaktiven Zustand (`WIDGET_STATE_INACTIVE`).

Beispiel:

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

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

[comment]: # ({a26add25-06e3db00})
Die Methode ***onDestroy()*** führt Bereinigungsaufgaben aus, bevor das Widget aus dem Dashboard gelöscht wird.
Dazu kann gehören, eine Datenbankverbindung zu schließen, die während der Widget-Initialisierung aufgebaut wurde,
temporäre Daten zu bereinigen, um Systemspeicher freizugeben und Ressourcenlecks zu vermeiden,
sowie Event-Listener im Zusammenhang mit Größenänderungsereignissen oder Button-Klicks abzumelden, um unnötige Ereignisverarbeitung und Speicherlecks zu verhindern usw.
Diese Methode wird aufgerufen, wenn das Widget oder die Dashboard-Seite, die es enthält, gelöscht wird.

Beachten Sie, dass ein Widget im aktiven Zustand (`WIDGET_STATE_ACTIVE`) immer zuerst durch Aufruf der Methode *onDeactivate()* deaktiviert wird, bevor die Methode *onDestroy()* aufgerufen wird.

Beispiel:

```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})
Die Methode ***onEdit()*** definiert das Erscheinungsbild und Verhalten des Widgets, wenn das Dashboard in den Bearbeitungsmodus wechselt.
Diese Methode wird aufgerufen, wenn das Dashboard in den Bearbeitungsmodus wechselt, typischerweise wenn ein Benutzer mit der Schaltfläche *Edit* des Widgets oder der Schaltfläche *Edit dashboard* des Dashboards interagiert.

Beispiel:

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

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

[comment]: # ({1e54f2e8-87f28aae})
##### Methoden des Aktualisierungsprozesses

Die Methoden des Widget-Aktualisierungsprozesses sind dafür verantwortlich, aktualisierte Daten vom Zabbix-Server oder einer anderen Datenquelle abzurufen und im Widget anzuzeigen.

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

[comment]: # ({fa94eb63-c743ab46})
Die Methode ***promiseUpdate()*** startet den Datenaktualisierungsprozess, indem sie Daten abruft, typischerweise über Webanfragen oder API-Aufrufe.
Diese Methode wird aufgerufen, wenn eine Dashboard-Seite angezeigt wird, und danach in regelmäßigen Abständen, bis zu einer anderen Dashboard-Seite gewechselt wird.

Im Folgenden sehen Sie ein Beispiel für die Standardimplementierung der Methode *promiseUpdate()*, die von den meisten nativen Zabbix-Widgets verwendet wird.
In der Standardimplementierung folgt die Methode *promiseUpdate()* einem allgemeinen Muster zum Abrufen von Daten vom Server.
Sie erstellt ein neues `Curl`-Objekt mit der entsprechenden URL und den Anfrageparametern,
sendet mit der Methode *fetch()* eine `POST`-Anfrage unter Verwendung des Datenobjekts, das von der Methode *getUpdateRequestData()* erstellt wird,
und verarbeitet die Antwort (oder eine Fehlerantwort) entsprechend mit *processUpdateResponse(response)* oder *processUpdateErrorResponse(error)*.
Diese Implementierung eignet sich für die meisten Widgets, da sie Daten in der Regel im JSON-Format abrufen und diese auf konsistente Weise verarbeiten.

```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})
Die Methode ***getUpdateRequestData()*** bereitet die Server-Anfragedaten für die Aktualisierung des Widgets vor, indem sie verschiedene Eigenschaften und ihre entsprechenden Werte (Widget-Kennungen, Filtereinstellungen, Zeitbereiche usw.) aus dem Zustand und der Konfiguration des Widgets sammelt
und ein Datenobjekt erstellt, das die erforderlichen Informationen darstellt, die in der Aktualisierungsanfrage an den Server gesendet werden sollen.
Diese Methode wird nur als Teil der Standardmethode *promiseUpdate()* aufgerufen, also während des Widget-Aktualisierungsprozesses.

Standardimplementierung:

```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})
Die Methode ***processUpdateResponse(response)*** verarbeitet die Antwort, die nach der Aktualisierungsanfrage vom Server empfangen wird,
und löscht, wenn der Aktualisierungsprozess erfolgreich und fehlerfrei war, die Widget-Daten und zeigt mit der Methode *setContents()* neue Inhalte an.
Diese Methode wird nur als Teil der Standardmethode *promiseUpdate()* aufgerufen, also während des Widget-Aktualisierungsprozesses.

Standardimplementierung:

```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})
Die Methode ***processUpdateErrorResponse(error)*** verarbeitet die vom Server nach der Aktualisierungsanfrage empfangene Antwort, wenn die Antwort ein Fehler ist, und zeigt die Fehlermeldung/-en an.
Diese Methode wird nur als Teil der Standardmethode *promiseUpdate()* aufgerufen, also während des Widget-Aktualisierungsprozesses.

Standardimplementierung:

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

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

[comment]: # ({31ffc8a7-8ea0452d})
Die Methode ***setContents(response)*** zeigt den Inhalt des Widgets an, wenn der Widget-Aktualisierungsprozess erfolgreich und ohne Fehler abgeschlossen wurde,
was unter anderem die Bearbeitung von DOM-Elementen, das Aktualisieren von UI-Komponenten, das Anwenden von Stilen oder Formatierungen usw. umfassen kann.
Diese Methode wird nur als Teil der Standardmethode *processUpdateResponse(response)* aufgerufen, also während der Verarbeitung der Antwort, die nach der Aktualisierungsanfrage vom Server empfangen wurde.

Standardimplementierung:

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

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

[comment]: # ({7b8ba0e6-95f750ef})
##### Methoden zur Änderung der Darstellung

Die Methoden zur Änderung der Widget-Präsentation sind für die Änderung des Erscheinungsbildes der Widgets zuständig.

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

[comment]: # ({5e245dd6-b5613994})
Die Methode ***onResize()*** ist dafür verantwortlich, die visuellen Elemente des Widgets an die neue Widget-Größe anzupassen,
was unter anderem das Neuanordnen von Elementen, das Anpassen von Elementabmessungen, das Kürzen von Text, die Implementierung von Lazy Loading zur Verbesserung der Reaktionsfähigkeit während der Größenänderung usw. umfassen kann.
Diese Methode wird aufgerufen, wenn die Größe des Widgets geändert wird, zum Beispiel wenn der Benutzer die Größe des Widgets manuell ändert oder wenn die Größe des Browserfensters geändert wird.

Beispiel:

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

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

[comment]: # ({d22bedba-88b32413})
Die Methode ***hasPadding()*** ist dafür verantwortlich, am unteren Rand des Widgets einen vertikalen Innenabstand von 8 px anzuwenden, wenn es so konfiguriert ist, dass [sein Header angezeigt wird](/manual/web_interface/frontend_sections/dashboards/widgets#common-parameters).
Diese Methode wird aufgerufen, wenn die Dashboard-Seite aktiviert wird, also wenn sie zur in der Benutzeroberfläche angezeigten Seite wird.

Standardimplementierung:

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

Bei einigen Widgets ist es erforderlich, den gesamten verfügbaren Widget-Bereich zu nutzen, um beispielsweise eine benutzerdefinierte Hintergrundfarbe zu konfigurieren.
Im Folgenden sehen Sie ein Beispiel für die Implementierung der Methode *hasPadding()*, die im nativen Zabbix-Widget [*Datenpunktwert*](/manual/web_interface/frontend_sections/dashboards/widgets/item_value) verwendet wird.

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

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