[comment]: # aside:2

[comment]: # ({04e47dfc-fa26c138})
# Erstellen eines Widgets (Tutorial)

[comment]: # ({/04e47dfc-fa26c138})

[comment]: # ({14b8f451-386f5763})
Dies ist ein Schritt-für-Schritt Tutorial, welches dir zeigt, wie man ein einfaches Zabbix-Frontend-Modul erstellt.
Sie können alle Dateien dieses Moduls als ZIP-Archiv herunterladen: [MyAddress.zip](../../../../assets/en/devel/modules/examples/MyAddress.zip).

[comment]: # ({/14b8f451-386f5763})

[comment]: # ({6bed8352-dead8e1e})
## Was Sie erstellen werden

In diesem Tutorial erstellen Sie zunächst ein [einfaches](#part-i---hello-world) "Hello, world!"-Widget und wandeln es dann in ein [fortgeschritteneres](#part-ii---gauge-chart) Widget um, das einen Datenpunktwert als Tachometerdiagramm anzeigt.
So wird das fertige Widget aussehen:

![](../../../../assets/en/devel/modules/tutorials/widget/widget_view_finished.png){width="600"}

[comment]: # ({/6bed8352-dead8e1e})

[comment]: # ({156649db-03fc601d})
## Teil I – "Hallo Welt!“

In diesem Abschnitt erfahren Sie, wie Sie die minimal erforderlichen Widget-Elemente erstellen und ein neues Widget zum Zabbix-Frontend hinzufügen.

[comment]: # ({/156649db-03fc601d})

[comment]: # ({deec5ed3-ac51379a})
### Ein leeres Widget zum Zabbix-Frontend hinzufügen

1. Erstellen Sie ein Verzeichnis *lesson_gauge_chart* im Verzeichnis *modules* Ihrer Zabbix-Frontend-Installation (zum Beispiel *zabbix/ui/modules*).

::: noteclassic
Alle benutzerdefinierten Widgets werden als externe Module behandelt und müssen dem Verzeichnis *modules* Ihrer Zabbix-Frontend-Installation hinzugefügt werden (zum Beispiel *zabbix/ui/modules*).
Das Verzeichnis *zabbix/ui/widgets* ist für die integrierten Zabbix-Widgets reserviert und wird zusammen mit der Zabbix-UI aktualisiert.
:::

2. Erstellen Sie eine Datei *manifest.json* mit grundlegenden Widget-Metadaten (siehe die Beschreibung der unterstützten [Parameter](../file_structure/manifest)).

**ui/modules/lesson_gauge_chart/manifest.json**

```json
{
    "manifest_version": 2.0,
    "id": "lesson_gauge_chart",
    "type": "widget",
    "name": "Gauge chart",
    "namespace": "LessonGaugeChart",
    "version": "1.1",
    "author": "Zabbix"
}
```

3. Gehen Sie in der Zabbix-Frontend zu *Administration → Allgemein → Module* und klicken Sie auf die Schaltfläche *Verzeichnis scannen*.

![](../../../../assets/en/devel/modules/tutorials/widget/scan_dir.png)

4. Suchen Sie in der Liste das neue Modul *Gauge chart* und klicken Sie auf den Hyperlink "Disabled", um den Status des Moduls von "Disabled" auf "Enabled" zu ändern (falls das Modul nicht aufgeführt ist, siehe Abschnitt [Fehlerbehebung](/manual/extensions/frontendmodules#installation)).

![](../../../../assets/en/devel/modules/tutorials/widget/widget_register.png){width="600"}

5. Öffnen Sie ein Dashboard, wechseln Sie in den Bearbeitungsmodus und fügen Sie ein neues Widget hinzu.
Wählen Sie im Feld *Type* "Gauge chart" aus.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_add.png){width="600"}

6. Zu diesem Zeitpunkt enthält die Konfiguration des Widgets *Gauge chart* nur die allgemeinen Widget-Felder *Name* und *Aktualisierungsintervall*.
Klicken Sie auf *Add*, um das Widget dem Dashboard hinzuzufügen.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_conf_b.png){width="600"}

7. Ein leeres Widget sollte auf dem Dashboard erscheinen.
Klicken Sie oben rechts auf *Save changes*, um das Dashboard zu speichern.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_blank_b.png){width="600"}

[comment]: # ({/deec5ed3-ac51379a})

[comment]: # ({6ca1b1e7-a953cd01})
### Eine widget-Ansicht hinzufügen

:::noteclassic
Die **Ansichts**-Datei des Widgets sollte sich im Verzeichnis *views* befinden (für dieses Tutorial: *ui/modules/lesson_gauge_chart/views/*).
Wenn die Datei den Standardnamen *widget.view.php* hat, müssen Sie sie nicht in der Datei *manifest.json* registrieren.
Wenn die Datei einen anderen Namen hat, geben Sie ihn im Abschnitt *actions/widget.lesson_gauge_chart.view* der Datei [manifest.json](/devel/modules/file_structure/manifest) an.
:::

1. Erstellen Sie im Verzeichnis *lesson_gauge_chart* ein Verzeichnis *views*.

2. Erstellen Sie im Verzeichnis *views* eine Datei *widget.view.php*.

**ui/modules/lesson_gauge_chart/views/widget.view.php**

```php
<?php

/**
 * Gauge-chart-widget-Ansicht.
 *
 * @var CView $this
 * @var array $data
 */

(new CWidgetView($data))
    ->addItem(
        new CTag('h1', true, 'Hello, world!')
    )
    ->show();
```

3. Aktualisieren Sie das Dashboard.
Das Widget *Gauge chart* zeigt jetzt „Hello, world!“ an.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_hello_world.png){width="600"}

[comment]: # ({/6ca1b1e7-a953cd01})

[comment]: # ({f5b50cf9-b89998cf})
## Teil II – Gauge Chart (Messgerätetabelle)

[comment]: # ({/f5b50cf9-b89998cf})

[comment]: # ({05a33fe2-b23d5e39})
### Einstellungen zu einer Konfigurationsansicht hinzufügen und in einer Widget-Ansicht verwenden

In diesem Abschnitt erfahren Sie, wie Sie ein Widget-Konfigurationsfeld hinzufügen und den eingegebenen Wert in der Widget-Ansicht als Text anzeigen.

Die Widget-Konfiguration besteht aus einem Formular (*Zabbix\\Widgets\\CWidgetForm*) und einer Widget-Formularansicht (*widget.edit.php*).
Um Felder (*Zabbix\\Widgets\\CWidgetField*) hinzuzufügen, müssen Sie eine *WidgetForm*-Klasse erstellen, die *Zabbix\\Widgets\\CWidgetForm* erweitert.

Das Formular enthält eine Reihe von Feldern (*Zabbix\\Widgets\\CWidgetField*) verschiedener Typen, die zur Validierung der vom Benutzer eingegebenen Werte verwendet werden.
Das Formularfeld (*Zabbix\\Widgets\\CWidgetField*) für jeden Eingabeelementtyp konvertiert den Wert in ein einheitliches Format, um ihn in der Datenbank zu speichern.

:::noteclassic
Die **Formular**-Datei des Widgets sollte sich im Verzeichnis *includes* befinden (für dieses Tutorial: *ui/modules/lesson_gauge_chart/includes/*).
Wenn die Datei den Standardnamen *WidgetForm.php* hat, müssen Sie sie nicht in der Datei *manifest.json* registrieren.
Wenn die Datei einen anderen Namen hat, geben Sie sie im Abschnitt *widget/form_class* der Datei [manifest.json](/devel/modules/file_structure/manifest) an.
:::

1. Erstellen Sie ein neues Verzeichnis *includes* im Verzeichnis *lesson_gauge_chart*.

2. Erstellen Sie eine Datei *WidgetForm.php* im Verzeichnis *includes*.

**ui/modules/lesson_gauge_chart/includes/WidgetForm.php**

```php
<?php

namespace Modules\LessonGaugeChart\Includes;

use Zabbix\Widgets\CWidgetForm;

class WidgetForm extends CWidgetForm {
}
```

3. Fügen Sie dem Widget-Konfigurationsformular ein Feld *Description* hinzu.
Dies ist ein reguläres Textfeld, in das ein Benutzer beliebige Zeichen eingeben kann.
Dafür können Sie die Klasse *CWidgetFieldTextBox* verwenden.

**ui/modules/lesson_gauge_chart/includes/WidgetForm.php**

```php
<?php

namespace Modules\LessonGaugeChart\Includes;

use Zabbix\Widgets\CWidgetForm;

use Zabbix\Widgets\Fields\CWidgetFieldTextBox;

class WidgetForm extends CWidgetForm {

    public function addFields(): self {
        return $this
            ->addField(
               new CWidgetFieldTextBox('description', _('Description'))
            );
   }
}
```

4. Erstellen Sie im Verzeichnis *views* eine Widget-Konfigurationsansichtsdatei *widget.edit.php* und fügen Sie eine Ansicht für das neue Feld *Description* hinzu.
Für die Feldklasse *CWidgetFieldTextBox* lautet die Ansicht *CWidgetFieldTextBoxView*.

**ui/modules/lesson_gauge_chart/views/widget.edit.php**

```php
<?php

/**
 * Gauge chart widget form view.
 *
 * @var CView $this
 * @var array $data
 */

(new CWidgetFormView($data))
    ->addField(
        new CWidgetFieldTextBoxView($data['fields']['description'])
    )
    ->show();
```

5. Gehen Sie zum Dashboard und klicken Sie im Widget auf das Zahnradsymbol, um das Widget-Konfigurationsformular zu öffnen.

6. Das Widget-Konfigurationsformular enthält jetzt ein neues Textfeld *Description*.
Geben Sie einen beliebigen Wert ein, zum Beispiel *Gauge chart description*.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_conf_descr.png){width="600"}

7. Klicken Sie im Widget-Konfigurationsformular auf *Apply*.
Klicken Sie dann oben rechts auf *Save changes*, um das Dashboard zu speichern.
Beachten Sie, dass die neue Beschreibung nirgendwo sichtbar ist und das Widget weiterhin "Hello, world!" anzeigt.

Damit die neue Beschreibung im Widget angezeigt wird, muss der Wert des Felds *Description* aus der Datenbank abgerufen und an die Widget-Ansicht übergeben werden.
Dafür müssen Sie eine Aktionsklasse erstellen.

8. Erstellen Sie ein neues Verzeichnis *actions* im Verzeichnis *lesson_gauge_chart*.

9. Erstellen Sie eine Datei *WidgetView.php* im Verzeichnis *actions*.
Die Aktionsklasse *WidgetView* erweitert die Klasse *CControllerDashboardWidgetView*.

Die Werte der Widget-Konfigurationsfelder werden in der Eigenschaft **$fields_values** der Aktionsklasse gespeichert.

**ui/modules/lesson_gauge_chart/actions/WidgetView.php**

```php
<?php

namespace Modules\LessonGaugeChart\Actions;

use CControllerDashboardWidgetView,
    CControllerResponseData;

class WidgetView extends CControllerDashboardWidgetView {

    protected function doAction(): void {
        $this->setResponse(new CControllerResponseData([
            'name' => $this->getInput('name', $this->widget->getName()),
            'description' => $this->fields_values['description'],
            'user' => [
                'debug_mode' => $this->getDebugMode()
            ]
        ]));
    }
}
```

10. Öffnen Sie *manifest.json* und registrieren Sie *WidgetView* als Aktionsklasse im Abschnitt *actions/widget.lesson_gauge_chart.view*.

**ui/modules/lesson_gauge_chart/manifest.json**

```json
{
    "manifest_version": 2.0,
    "id": "lesson_gauge_chart",
    "type": "widget",
    "name": "Gauge chart",
    "namespace": "LessonGaugeChart",
    "version": "1.0",
    "author": "Zabbix",
    "actions": {
        "widget.lesson_gauge_chart.view": {
            "class": "WidgetView"
        }
    }
}
```

11. Jetzt können Sie den Wert des Felds *description*, der in *$data['description']* enthalten ist, in der Widget-Ansicht verwenden.
Öffnen Sie *views/widget.view.php* und ersetzen Sie den statischen Text "Hello, world!" durch *$data['description']*.

**ui/modules/lesson_gauge_chart/views/widget.view.php**

```php
<?php

/**
 * Gauge chart widget view.
 *
 * @var CView $this
 * @var array $data
 */

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

12. Aktualisieren Sie die Dashboard-Seite.
Sie sollten nun den Beschreibungstext des Widgets anstelle von "Hello, world!" sehen.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_view_descr.png){width="600"}

[comment]: # ({/05a33fe2-b23d5e39})

[comment]: # ({25dcaffc-3f0e28b2})
### Einen Datenpunktwert über die API abrufen

Das Widget sollte den letzten Wert eines vom Benutzer ausgewählten Datenpunkts anzeigen.
Dazu müssen Sie die Möglichkeit hinzufügen, Datenpunkte in der Widget-Konfiguration auszuwählen.

In diesem Abschnitt erfahren Sie, wie Sie dem Widget-Formular ein Feld zur Auswahl eines Datenpunkts hinzufügen und wie Sie die visuelle Darstellung dieses Felds in der Konfigurationsansicht ergänzen.
Anschließend kann der Widget-Controller die Datenpunktdaten und deren Wert über eine API-Anfrage abrufen.
Nach dem Empfang kann der Wert in der Widget-Ansicht angezeigt werden.

1. Öffnen Sie *includes/WidgetForm.php* und fügen Sie das Feld *CWidgetFieldMultiSelectItem* hinzu.
Dies ermöglicht die Auswahl eines Datenpunkts im Konfigurationsformular.

**ui/modules/lesson_gauge_chart/includes/WidgetForm.php**

```php
<?php

namespace Modules\LessonGaugeChart\Includes;

use Zabbix\Widgets\{
    CWidgetField,
    CWidgetForm
};

use Zabbix\Widgets\Fields\{
    CWidgetFieldMultiSelectItem,
    CWidgetFieldTextBox
};

/**
 * Gauge chart widget form.
 */
class WidgetForm extends CWidgetForm {
    
    public function addFields(): self {
        return $this
            ->addField(
                (new CWidgetFieldMultiSelectItem('itemid', _('Item')))
                    ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
                    ->setMultiple(false)
            )
            ->addField(
                new CWidgetFieldTextBox('description', _('Description'))
            );
    }
}
```

2. Öffnen Sie *views/widget.edit.php* und fügen Sie die visuelle Komponente des Felds zur Konfigurationsansicht hinzu.

**ui/modules/lesson_gauge_chart/views/widget.edit.php**

```php
<?php

/**
 * Gauge chart widget form view.
 *
 * @var CView $this
 * @var array $data
 */

(new CWidgetFormView($data))
    ->addField(
        new CWidgetFieldMultiSelectItemView($data['fields']['itemid'])
    )
    ->addField(
        new CWidgetFieldTextBoxView($data['fields']['description'])
    )
    ->show();
```

3. Kehren Sie zum Dashboard zurück und klicken Sie im Widget auf das Zahnradsymbol, um das Widget-Konfigurationsformular zu öffnen.

4. Das Widget-Konfigurationsformular enthält nun ein neues Eingabefeld *Item*.
Wählen Sie den Host "Zabbix server" und den Datenpunkt "Load average (1m avg)" aus.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_conf_item.png){width=600}

5. Klicken Sie im Widget-Konfigurationsformular auf *Apply*.
Klicken Sie anschließend oben rechts auf *Save changes*, um das Dashboard zu speichern.

6. Öffnen und bearbeiten Sie *actions/WidgetView.php*.

Ab jetzt ist die Datenpunkt-ID im Widget-Controller unter *$this->fields_values\['itemid'\]* verfügbar.
Die Controller-Methode *doAction()* ermittelt die Datenpunktdaten (Name, Wertetyp, Einheiten) mithilfe der API-Methode *[item.get](/manual/api/reference/item/get)* und den letzten Wert des Datenpunkts mithilfe der API-Methode *[history.get](/manual/api/reference/history/get)*.

**ui/modules/lesson_gauge_chart/actions/WidgetView.php**

```php
<?php

namespace Modules\LessonGaugeChart\Actions;

use API,
    CControllerDashboardWidgetView,
    CControllerResponseData;

class WidgetView extends CControllerDashboardWidgetView {

    protected function doAction(): void {
        $db_items = API::Item()->get([
            'output' => ['itemid', 'value_type', 'name', 'units'],
            'itemids' => $this->fields_values['itemid'],
            'webitems' => true,
            'filter' => [
                'value_type' => [ITEM_VALUE_TYPE_UINT64, ITEM_VALUE_TYPE_FLOAT]
            ]
        ]);

        $value = null;

        if ($db_items) {
            $item = $db_items[0];

            $history = API::History()->get([
                'output' => API_OUTPUT_EXTEND,
                'itemids' => $item['itemid'],
                'history' => $item['value_type'],
                'sortfield' => 'clock',
                'sortorder' => ZBX_SORT_DOWN,
                'limit' => 1
            ]);

            if ($history) {
                $value = convertUnitsRaw([
                    'value' => $history[0]['value'],
                    'units' => $item['units']
                ]);
            }
        }

        $this->setResponse(new CControllerResponseData([
            'name' => $this->getInput('name', $this->widget->getName()),
            'value' => $value,
            'description' => $this->fields_values['description'],
            'user' => [
                'debug_mode' => $this->getDebugMode()
            ]
        ]));
    }
}
```

7. Öffnen Sie *views/widget.view.php* und fügen Sie den Datenpunktwert zur Widget-Ansicht hinzu.

**ui/modules/lesson_gauge_chart/views/widget.view.php**

```php
<?php

/**
 * Gauge chart widget view.
 *
 * @var CView $this
 * @var array $data
 */

(new CWidgetView($data))
    ->addItem([
        new CTag('h1', true, $data['description']),
        new CDiv($data['value'] !== null ? $data['value']['value'] : _('No data'))
    ])
    ->show();
```

8. Aktualisieren Sie die Dashboard-Seite.
Das Widget zeigt den neuesten Datenpunktwert an.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_view_item.png){width="600"}

[comment]: # ({/25dcaffc-3f0e28b2})

[comment]: # ({aa1b47ba-8f001ece})
### Erweiterte Konfigurationseinstellungen zu einer Konfigurationsansicht hinzufügen

In diesem Abschnitt erfahren Sie, wie Sie einen ein- und ausklappbaren Abschnitt *Erweiterte Konfiguration* mit optionalen Parametern hinzufügen, z. B. Farbe, Mindest- und Höchstwerte, Einheiten und das zuvor erstellte Feld *Description*.

1. Erstellen Sie im Hauptverzeichnis des Widgets *lesson_gauge_chart* eine Datei *Widget.php*, um eine neue Klasse *Widget* zu erstellen.

Die Klasse *Widget* erweitert die Basisklasse *CWidget*, um die standardmäßigen Widget-Einstellungen hinzuzufügen bzw. zu überschreiben (in diesem Fall - Übersetzungen).
Das unten bereitgestellte JavaScript zeigt den String "No data" an, wenn keine Daten vorhanden sind.
Der String "No data" ist in den Zabbix-UI-Übersetzungsdateien vorhanden.

Wenn es Widget-Konstanten gibt, wird empfohlen, diese ebenfalls in der Klasse *Widget* anzugeben.

**ui/modules/lesson_gauge_chart/Widget.php**

```php
<?php

namespace Modules\LessonGaugeChart;

use Zabbix\Core\CWidget;

class Widget extends CWidget {

    public const UNIT_AUTO = 0;
    public const UNIT_STATIC = 1;

    public function getTranslationStrings(): array {
        return [
            'class.widget.js' => [
                'No data' => _('No data')
            ]
        ];
    }
}
```

2. Öffnen Sie *includes/WidgetForm.php* und fügen Sie die neuen Felder *Color* (Farbauswahl), *Min* (numerisches Feld), *Max* (numerisches Feld) und *Units* (Auswahl) hinzu, und definieren Sie die Standard-Farbpalette für die Farbauswahl, damit sie in den nächsten Schritten verwendet werden kann.

**ui/modules/lesson_gauge_chart/includes/WidgetForm.php**

```php
<?php

namespace Modules\LessonGaugeChart\Includes;

use Modules\LessonGaugeChart\Widget;

use Zabbix\Widgets\{
    CWidgetField,
    CWidgetForm
};

use Zabbix\Widgets\Fields\{
    CWidgetFieldColor,
    CWidgetFieldMultiSelectItem,
    CWidgetFieldNumericBox,
    CWidgetFieldSelect,
    CWidgetFieldTextBox
};

/**
 * Gauge chart widget form.
 */
class WidgetForm extends CWidgetForm {

    public const DEFAULT_COLOR_PALETTE = [
        'FF465C', 'B0AF07', '0EC9AC', '524BBC', 'ED1248', 'D1E754', '2AB5FF', '385CC7', 'EC1594', 'BAE37D',
        '6AC8FF', 'EE2B29', '3CA20D', '6F4BBC', '00A1FF', 'F3601B', '1CAE59', '45CFDB', '894BBC', '6D6D6D'
    ];

    public function addFields(): self {
        return $this
            ->addField(
                (new CWidgetFieldMultiSelectItem('itemid', _('Item')))
                    ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
                    ->setMultiple(false)
            )
            ->addField(
                (new CWidgetFieldColor('chart_color', _('Color')))->setDefault('FF0000')
            )
            ->addField(
                (new CWidgetFieldNumericBox('value_min', _('Min')))
                    ->setDefault(0)
                    ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
            )
            ->addField(
                (new CWidgetFieldNumericBox('value_max', _('Max')))
                    ->setDefault(100)
                    ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
            )
            ->addField(
                (new CWidgetFieldSelect('value_units', _('Units'), [
                    Widget::UNIT_AUTO => _x('Auto', 'history source selection method'),
                    Widget::UNIT_STATIC => _x('Static', 'history source selection method')
                ]))->setDefault(Widget::UNIT_AUTO)
            )
            ->addField(
                (new CWidgetFieldTextBox('value_static_units'))
            )
            ->addField(
                new CWidgetFieldTextBox('description', _('Description'))
            );
    }
}
```

3. Öffnen Sie *views/widget.edit.php* und fügen Sie die visuellen Komponenten der Felder zur Konfigurationsansicht hinzu.

**ui/modules/lesson_gauge_chart/views/widget.edit.php**

```php
<?php

/**
 * Gauge chart widget form view.
 *
 * @var CView $this
 * @var array $data
 */

$lefty_units = new CWidgetFieldSelectView($data['fields']['value_units']);
$lefty_static_units = (new CWidgetFieldTextBoxView($data['fields']['value_static_units']))
    ->setPlaceholder(_('value'))
    ->setWidth(ZBX_TEXTAREA_TINY_WIDTH);

(new CWidgetFormView($data))
    ->addField(
        (new CWidgetFieldMultiSelectItemView($data['fields']['itemid']))
            ->setPopupParameter('numeric', true)
    )
    ->addFieldset(
        (new CWidgetFormFieldsetCollapsibleView(_('Advanced configuration')))
            ->addField(
                new CWidgetFieldColorView($data['fields']['chart_color'])
            )
            ->addField(
                new CWidgetFieldNumericBoxView($data['fields']['value_min'])
            )
            ->addField(
                new CWidgetFieldNumericBoxView($data['fields']['value_max'])
            )
            ->addItem([
                $lefty_units->getLabel(),
                (new CFormField([
                    $lefty_units->getView()->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
                    $lefty_static_units->getView()
                ]))
            ])
            ->addField(
                new CWidgetFieldTextBoxView($data['fields']['description'])
            )
    )
    ->show();
```

::: noteclassic
Die Methode *addField()* der Klasse *CWidgetFormView* nimmt als zweiten Parameter eine CSS-Klassenzeichenfolge entgegen.
:::

4. Kehren Sie zum Dashboard zurück, wechseln Sie in den Bearbeitungsmodus und klicken Sie auf das Zahnradsymbol im Widget, um das Konfigurationsformular des Widgets zu öffnen.
Das Konfigurationsformular des Widgets enthält nun einen neuen ein- und ausklappbaren Abschnitt *Erweiterte Konfiguration*.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_conf_advanced.png){width="600"}

5. Klappen Sie den Abschnitt *Erweiterte Konfiguration* auf, um zusätzliche Konfigurationsfelder des Widgets anzuzeigen.
Beachten Sie, dass das Feld *Color* noch keine Farbauswahl hat.
Das liegt daran, dass die Farbauswahl mit JavaScript initialisiert werden muss, das im nächsten Abschnitt hinzugefügt wird - [*JavaScript zum Widget hinzufügen*](#add-javascript-to-the-widget).

![](../../../../assets/en/devel/modules/tutorials/widget/widget_conf_advanced_a.png){width="600"}

[comment]: # ({/aa1b47ba-8f001ece})

[comment]: # ({91129a2b-c573cc71})
### JavaScript zum Widget hinzufügen

In diesem Abschnitt lernen Sie, wie Sie ein Gauge-Diagramm hinzufügen - erstellt mit JavaScript -, das anzeigt, ob der letzte Wert normal oder zu hoch/zu niedrig ist.

1. Erstellen Sie eine Datei *widget.edit.js.php* im Verzeichnis *views*.

JavaScript ist dafür verantwortlich, den Color Picker in der Konfigurationsansicht zu initialisieren.

**ui/modules/lesson_gauge_chart/views/widget.edit.js.php**

```php
<?php

use Modules\LessonGaugeChart\Widget;

?>

window.widget_lesson_gauge_chart_form = new class {

    init({color_palette}) {
        this._unit_select = document.getElementById('value_units');
        this._unit_value = document.getElementById('value_static_units');

        this._unit_select.addEventListener('change', () => this.updateForm());

        colorPalette.setThemeColors(color_palette);

        for (const colorpicker of jQuery('.<?= ZBX_STYLE_COLOR_PICKER ?> input')) {
            jQuery(colorpicker).colorpicker();
        }

        const overlay = overlays_stack.getById('widget_properties');

        for (const event of ['overlay.reload', 'overlay.close']) {
            overlay.$dialogue[0].addEventListener(event, () => { jQuery.colorpicker('hide'); });
        }

        this.updateForm();
    }

    updateForm() {
        this._unit_value.disabled = this._unit_select.value == <?= Widget::UNIT_AUTO ?>;
    }
};
```

2. Öffnen Sie *views/widget.edit.php* und fügen Sie die Datei *widget.edit.js.php* mit dem JavaScript zur Konfigurationsansicht hinzu.
Verwenden Sie dazu die Methode *includeJsFile()*.
Um Inline-JavaScript hinzuzufügen, verwenden Sie die Methode *addJavaScript()*.

**ui/modules/lesson_gauge_chart/views/widget.edit.php**

```php
<?php

/**
 * Gauge chart widget form view.
 *
 * @var CView $this
 * @var array $data
 */

use Modules\LessonGaugeChart\Includes\WidgetForm;

$lefty_units = new CWidgetFieldSelectView($data['fields']['value_units']);
$lefty_static_units = (new CWidgetFieldTextBoxView($data['fields']['value_static_units']))
    ->setPlaceholder(_('value'))
    ->setWidth(ZBX_TEXTAREA_TINY_WIDTH);

(new CWidgetFormView($data))
    ->addField(
        (new CWidgetFieldMultiSelectItemView($data['fields']['itemid']))
            ->setPopupParameter('numeric', true)
    )
    ->addFieldset(
        (new CWidgetFormFieldsetCollapsibleView(_('Advanced configuration')))
            ->addField(
                new CWidgetFieldColorView($data['fields']['chart_color'])
            )
            ->addField(
                new CWidgetFieldNumericBoxView($data['fields']['value_min'])
            )
            ->addField(
                new CWidgetFieldNumericBoxView($data['fields']['value_max'])
            )
            ->addItem([
                $lefty_units->getLabel(),
                (new CFormField([
                    $lefty_units->getView()->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
                    $lefty_static_units->getView()
                ]))
            ])
            ->addField(
                new CWidgetFieldTextBoxView($data['fields']['description'])
            )
    )
    ->includeJsFile('widget.edit.js.php')
    ->addJavaScript('widget_lesson_gauge_chart_form.init('.json_encode([
        'color_palette' => WidgetForm::DEFAULT_COLOR_PALETTE
    ], JSON_THROW_ON_ERROR).');')
    ->show();
```

3. Kehren Sie zum Dashboard zurück und klicken Sie auf das Zahnradsymbol im Widget, um das Konfigurationsformular zu öffnen.
Erweitern Sie nun den Abschnitt *Advanced configuration*, um den initialisierten Color Picker anzuzeigen.
Füllen Sie die Felder mit Werten aus und wählen Sie eine Farbe für das Gauge-Diagramm aus.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_conf_advanced_b.png){width="600"}

4. Klicken Sie im Widget-Konfigurationsformular auf *Apply*.
Klicken Sie anschließend oben rechts auf *Save changes*, um das Dashboard zu speichern.

5. Öffnen Sie *actions/WidgetView.php* und aktualisieren Sie den Controller.

Die Eigenschaft **$this->fields_values** enthält nun die Werte aller Felder aus *Advanced configuration*.
Vervollständigen Sie den Controller, damit die Konfiguration und der ausgewählte Item-Wert an die Widget-Ansicht übergeben werden können.

**ui/modules/lesson_gauge_chart/actions/WidgetView.php**

```php
<?php

namespace Modules\LessonGaugeChart\Actions;

use API,
    CControllerDashboardWidgetView,
    CControllerResponseData;

class WidgetView extends CControllerDashboardWidgetView {

    protected function doAction(): void {
        $db_items = API::Item()->get([
            'output' => ['itemid', 'value_type', 'name', 'units'],
            'itemids' => $this->fields_values['itemid'],
            'webitems' => true,
            'filter' => [
                'value_type' => [ITEM_VALUE_TYPE_UINT64, ITEM_VALUE_TYPE_FLOAT]
            ]
        ]);

        $history_value = null;

        if ($db_items) {
            $item = $db_items[0];

            $history = API::History()->get([
                'output' => API_OUTPUT_EXTEND,
                'itemids' => $item['itemid'],
                'history' => $item['value_type'],
                'sortfield' => 'clock',
                'sortorder' => ZBX_SORT_DOWN,
                'limit' => 1
            ]);

            if ($history) {
                $history_value = convertUnitsRaw([
                    'value' => $history[0]['value'],
                    'units' => $item['units']
                ]);
            }
        }

        $this->setResponse(new CControllerResponseData([
            'name' => $this->getInput('name', $this->widget->getName()),
            'history' => $history_value,
            'fields_values' => $this->fields_values,
            'user' => [
                'debug_mode' => $this->getDebugMode()
            ]
        ]));
    }
}
```

6. Öffnen und ändern Sie *views/widget.view.php*.

Sie müssen einen Container für das Gauge-Diagramm erstellen, das Sie in den nächsten Schritten zeichnen werden, sowie einen Container für die Beschreibung.

Um Werte als JSON-Objekt an JavaScript zu übergeben, verwenden Sie die Methode *setVar()*.

**ui/modules/lesson_gauge_chart/views/widget.view.php**

```php
<?php

/**
 * Gauge chart widget view.
 *
 * @var CView $this
 * @var array $data
 */

(new CWidgetView($data))
    ->addItem([
        (new CDiv())->addClass('chart'),
        $data['fields_values']['description']
            ? (new CDiv($data['fields_values']['description']))->addClass('description')
            : null
    ])
    ->setVar('history', $data['history'])
    ->setVar('fields_values', $data['fields_values'])
    ->show();
```

7. Erstellen Sie im Verzeichnis *lesson_gauge_chart* ein neues Verzeichnis *assets*.
Dieses Verzeichnis wird zum Speichern von JavaScript, CSS und möglicherweise weiteren Assets wie Schriftarten oder Bildern verwendet.

8. Erstellen Sie für das JavaScript der Widget-Ansicht im Verzeichnis *assets* ein Verzeichnis *js*.

9. Erstellen Sie im Verzeichnis *assets/js* eine Datei *class.widget.js*.

Diese JavaScript-Widget-Klasse erweitert die Basis-JavaScript-Klasse aller Dashboard-Widgets - *CWidget*.

Das Dashboard ist auf eine korrekte Implementierung eines Widgets angewiesen und kommuniziert alle relevanten Informationen an das Widget, indem die entsprechenden JavaScript-Methoden aufgerufen werden.
Das Dashboard erwartet außerdem, dass das Widget Ereignisse erzeugt, wenn eine Interaktion stattfindet.
Daher enthält die Klasse *CWidget* eine Reihe von Methoden mit der Standardimplementierung des Widget-Verhaltens, die durch Vererbung angepasst werden können.

In diesem Fall ist eine gewisse Anpassung erforderlich, daher wird benutzerdefinierte Logik für das folgende Widget-Verhalten implementiert:

-   Initialisierung des Widgets, die für die Definition des Anfangszustands des Widgets verantwortlich ist (siehe die Methode *onInitialize()*);
-   Anzeige des Widget-Inhalts (also das Zeichnen des Gauge-Diagramms), wenn der Aktualisierungsvorgang des Widgets erfolgreich und ohne Fehler abgeschlossen wurde (siehe die Methode *processUpdateResponse(response)* und die zugehörigen Methoden *\_resizeChart()* und *\_updatedChart()*)
-   Größenänderung des Widgets (siehe die Methode *onResize()* und die zugehörige Methode *\_resizeChart()*)

Für andere Aspekte des Gauge-Diagramm-Widgets wird die Standardimplementierung des Widget-Verhaltens verwendet.
Weitere Informationen zu den JavaScript-Methoden der Klasse *CWidget* finden Sie hier: [JavaScript](/devel/modules/widgets/presentation/javascript).

Da dieses JavaScript für die Widget-Ansicht erforderlich ist, sollte es mit der Dashboard-Seite geladen werden.
Um das Laden von JavaScript zu aktivieren, müssen Sie die Parameter *assets/js* und *js_class* in der Datei ***manifest.json*** aktualisieren, wie in Schritt 10 gezeigt.

**ui/modules/lesson_gauge_chart/assets/js/class.widget.js**

```js
class WidgetLessonGaugeChart extends CWidget {

    static UNIT_AUTO = 0;
    static UNIT_STATIC = 1;

    onInitialize() {
        super.onInitialize();

        this._refresh_frame = null;
        this._chart_container = null;
        this._canvas = null;
        this._chart_color = null;
        this._min = null;
        this._max = null;
        this._value = null;
        this._last_value = null;
        this._units = '';
    }

    processUpdateResponse(response) {
        if (response.history === null) {
            this._value = null;
            this._units = '';
        }
        else {
            this._value = Number(response.history.value);
            this._units = response.fields_values.value_units == WidgetLessonGaugeChart.UNIT_AUTO
                ? response.history.units
                : response.fields_values.value_static_units;
        }

        this._chart_color = response.fields_values.chart_color;
        this._min = Number(response.fields_values.value_min);
        this._max = Number(response.fields_values.value_max);

        super.processUpdateResponse(response);
    }

    setContents(response) {
        if (this._canvas === null) {
            super.setContents(response);

            this._chart_container = this._body.querySelector('.chart');
            this._chart_container.style.height =
                `${this._getContentsSize().height - this._body.querySelector('.description').clientHeight}px`;
            this._canvas = document.createElement('canvas');

            this._chart_container.appendChild(this._canvas);

            this._resizeChart();
        }

        this._updatedChart();
    }

    onResize() {
        super.onResize();

        if (this._state === WIDGET_STATE_ACTIVE) {
            this._resizeChart();
        }
    }

    _resizeChart() {
        const ctx = this._canvas.getContext('2d');
        const dpr = window.devicePixelRatio;

        this._canvas.style.display = 'none';
        const size = Math.min(this._chart_container.offsetWidth, this._chart_container.offsetHeight);
        this._canvas.style.display = '';

        this._canvas.width = size * dpr;
        this._canvas.height = size * dpr;

        ctx.scale(dpr, dpr);

        this._canvas.style.width = `${size}px`;
        this._canvas.style.height = `${size}px`;

        this._refresh_frame = null;

        this._updatedChart();
    }

    _updatedChart() {
        if (this._last_value === null) {
            this._last_value = this._min;
        }

        const start_time = Date.now();
        const end_time = start_time + 400;

        const animate = () => {
            const time = Date.now();

            if (time <= end_time) {
                const progress = (time - start_time) / (end_time - start_time);
                const smooth_progress = 0.5 + Math.sin(Math.PI * (progress - 0.5)) / 2;
                let value = this._value !== null ? this._value : this._min;
                value = (this._last_value + (value - this._last_value) * smooth_progress - this._min) / (this._max - this._min);

                const ctx = this._canvas.getContext('2d');
                const size = this._canvas.width;
                const char_weight = size / 12;
                const char_shadow = 3;
                const char_x = size / 2;
                const char_y = size / 2;
                const char_radius = (size - char_weight) / 2 - char_shadow;

                const font_ratio = 32 / 100;

                ctx.clearRect(0, 0, size, size);

                ctx.beginPath();
                ctx.shadowBlur = char_shadow;
                ctx.shadowColor = '#bbb';
                ctx.strokeStyle = '#eee';
                ctx.lineWidth = char_weight;
                ctx.lineCap = 'round';
                ctx.arc(char_x, char_y, char_radius, Math.PI * 0.749, Math.PI * 2.251, false);
                ctx.stroke();

                ctx.beginPath();
                ctx.strokeStyle = `#${this._chart_color}`;
                ctx.lineWidth = char_weight - 2;
                ctx.lineCap = 'round';
                ctx.arc(char_x, char_y, char_radius, Math.PI * 0.75,
                    Math.PI * (0.75 + (1.5 * Math.min(1, Math.max(0, value)))), false
                    );
                ctx.stroke();

                ctx.shadowBlur = 2;
                ctx.fillStyle = '#1f2c33';
                ctx.font = `${(char_radius * font_ratio)|0}px Arial`;
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                ctx.fillText(`${this._value !== null ? this._value : t('No data')}${this._units}`,
                    char_x, char_y, size - char_shadow * 4 - char_weight * 2
                );

                ctx.fillStyle = '#768d99';
                ctx.font = `${(char_radius * font_ratio * .5)|0}px Arial`;
                ctx.textBaseline = 'top';

                ctx.textAlign = 'left';
                ctx.fillText(`${this._min}${this._min != '' ? this._units : ''}`,
                    char_weight * .75, size - char_weight * 1.25, size / 2 - char_weight
                );

                ctx.textAlign = 'right';
                ctx.fillText(`${this._max}${this._max != '' ? this._units : ''}`,
                    size - char_weight * .75, size - char_weight * 1.25, size / 2 - char_weight
                );

                requestAnimationFrame(animate);
            }
            else {
                this._last_value = this._value;
            }
        };

        requestAnimationFrame(animate);
    }
}
```

10. Öffnen Sie *manifest.json* und fügen Sie hinzu:

- den Dateinamen (*class.widget.js*) zum Array im Abschnitt *assets/js*;
- den Klassennamen (*WidgetLessonGaugeChart*) zum Parameter *js_class* im Abschnitt *widget*.

Die Klasse *WidgetLessonGaugeChart* wird nun automatisch mit dem Dashboard geladen.

**ui/modules/lesson_gauge_chart/manifest.json**

```json
{
    "manifest_version": 2.0,
    "id": "lesson_gauge_chart",
    "type": "widget",
    "name": "Gauge chart",
    "namespace": "LessonGaugeChart",
    "version": "1.0",
    "author": "Zabbix",
    "actions": {
        "widget.lesson_gauge_chart.view": {
            "class": "WidgetView"
        }
    },
    "widget": {
        "js_class": "WidgetLessonGaugeChart"
    },
    "assets": {
        "js": ["class.widget.js"]
    }
}
```

[comment]: # ({/91129a2b-c573cc71})

[comment]: # ({6ea664c3-71184963})
### CSS-Stile zum Widget hinzufügen

In diesem Abschnitt erfahren Sie, wie Sie benutzerdefinierte CSS-Stile hinzufügen können, um das Widget ansprechender zu gestalten.

1. Für Widget-Stile erstellen Sie ein neues Verzeichnis *css* im Verzeichnis *assets*..

2. Erstellen Sie eine Datei *widget.css* im Verzeichnis *assets/css*.
Zur Gestaltung von Widget-Elementen verwenden Sie den Selektor *div.dashboard-widget-{widget id}*.
Um CSS für das gesamte Widget zu konfigurieren, verwenden Sie den Selektor *form.dashboard-widget-{widget id}*

**ui/modules/lesson_gauge_chart/assets/css/widget.css**

```css
div.dashboard-widget-lesson_gauge_chart {
    display: grid;
    grid-template-rows: 1fr;
    padding: 0;
}

div.dashboard-widget-lesson_gauge_chart .chart {
    display: grid;
    align-items: center;
    justify-items: center;
}

div.dashboard-widget-lesson_gauge_chart .chart canvas {
    background: white;
}

div.dashboard-widget-lesson_gauge_chart .description {
    padding-bottom: 8px;
    font-size: 1.750em;
    line-height: 1.2;
    text-align: center;
}

.dashboard-grid-widget-hidden-header div.dashboard-widget-lesson_gauge_chart .chart {
    margin-top: 8px;
}
```

3. Öffnen Sie *manifest.json* und fügen Sie den Namen der CSS-Datei (*widget.css*) in das Array im Abschnitt *assets/css* ein.
Dadurch können die in *widget.css* definierten CSS-Stile mit der Dashboard-Seite geladen werden.

**ui/modules/lesson_gauge_chart/manifest.json**

```json
{
    "manifest_version": 2.0,
    "id": "lesson_gauge_chart",
    "type": "widget",
    "name": "Gauge chart",
    "namespace": "LessonGaugeChart",
    "version": "1.0",
    "author": "Zabbix",
    "actions": {
        "widget.lesson_gauge_chart.view": {
            "class": "WidgetView"
        }
    },
    "widget": {
        "js_class": "WidgetLessonGaugeChart"
    },
    "assets": {
        "css": ["widget.css"],
        "js": ["class.widget.js"]
    }
}
```

4. Aktualisieren Sie die Dashboard-Seite, um die fertige Version des Widgets zu sehen.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_view_finished.png){width="600"}

[comment]: # ({/6ea664c3-71184963})

