[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]: # ({096b9349-dead8e1e})
## Was Sie erstellen werden

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

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

[comment]: # ({/096b9349-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]: # ({33e23fc9-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 integrierte Zabbix-Widgets reserviert und wird zusammen mit der Zabbix-UI aktualisiert.
:::

2. Erstellen Sie eine Datei *manifest.json* mit den 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 im Zabbix-Frontend zum Abschnitt *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 *Refresh interval*.
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]: # ({/33e23fc9-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]: # ({d1da3c35-b23d5e39})
### Einstellungen zu einer Konfigurationsansicht hinzufügen und sie 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 Klasse *WidgetForm* 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 **form**-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 ihn 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 gewöhnliches Textfeld, in das ein Benutzer beliebige Zeichen eingeben kann.
Sie können dafür 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* ist 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 erscheint, muss der Wert des Feldes *Description* aus der Datenbank abgerufen und an die Widget-Ansicht übergeben werden.
Dazu 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 Beschreibungsfeldes, 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 jetzt den Beschreibungstext des Widgets anstelle von „Hello, world!“ sehen.

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

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

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

Das Widget soll den letzten Wert eines Datenpunkts nach Wahl des Benutzers 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 Auswahlfeld für Datenpunkte hinzufügen und wie Sie den visuellen Teil dieses Feldes zur Konfigurationsansicht hinzufügen.
Anschließend kann der Widget-Controller Daten des Datenpunkts und dessen Wert über eine API-Anfrage abrufen.
Sobald der Wert empfangen wurde, kann er in der Widget-Ansicht angezeigt werden.

1. Öffnen Sie *includes/WidgetForm.php* und fügen Sie das Feld *CWidgetFieldMultiSelectItem* hinzu.
Damit kann im Konfigurationsformular ein Datenpunkt ausgewählt werden.

**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 Feldes 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 jetzt 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 dann oben rechts auf *Save changes*, um das Dashboard zu speichern.

6. Öffnen und ändern Sie *actions/WidgetView.php*.

Ab jetzt ist die Datenpunkt-ID im Widget-Controller in *$this->fields\_values\['itemid'\]* verfügbar.
Die Controller-Methode *doAction()* sammelt die Daten des Datenpunkts (Name, Werttyp, Einheiten) mit der API-Methode *[item.get](/manual/api/reference/item/get)* und den letzten Wert des Datenpunkts mit 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]: # ({/c52f5522-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 zu ergänzen 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* (Farbwähler), *Min* (numerisches Feld), *Max* (numerisches Feld) und *Units* (Auswahl) hinzu, und definieren Sie die Standard-Farbpalette für den Farbwähler, 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 im Widget auf das Zahnradsymbol, um das Widget-Konfigurationsformular zu öffnen.
Das Widget-Konfigurationsformular 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 Widget-Konfigurationsfelder anzuzeigen.
Beachten Sie, dass das Feld *Color* noch keinen Farbwähler hat.
Das liegt daran, dass der Farbwähler 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]: # ({175c9f96-c573cc71})
### JavaScript zum Widget hinzufügen

In diesem Abschnitt erfahren Sie, wie Sie ein Tachodiagramm hinzufügen – erstellt mit JavaScript –, das anzeigt, ob der letzte Wert normal oder zu hoch/zu niedrig ist.

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

JavaScript ist für die Initialisierung der Farbauswahl in der Konfigurationsansicht verantwortlich.

**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 im Widget auf das Zahnradsymbol, um das Widget-Konfigurationsformular zu öffnen.
Erweitern Sie nun den Abschnitt *Advanced configuration*, um die initialisierte Farbauswahl zu sehen.
Füllen Sie die Felder mit Werten aus und wählen Sie eine Farbe für das Tachodiagramm aus.

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

4. Klicken Sie im Widget-Konfigurationsformular auf *Apply*.
Klicken Sie dann 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 jetzt die Werte aller Felder aus *Advanced configuration*.
Vervollständigen Sie den Controller, damit die Konfiguration und der Wert des ausgewählten Datenpunkts 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 Tachodiagramm 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 gegebenenfalls 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 grundlegende JavaScript-Klasse aller Dashboard-Widgets – *CWidget*.

Das Dashboard ist auf eine korrekte Implementierung eines Widgets angewiesen und übermittelt dem Widget alle relevanten Informationen durch Aufruf der entsprechenden JavaScript-Methoden.
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 Erweiterung der Klasse angepasst werden kann.

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

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

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

Da dieses JavaScript für die Widget-Ansicht erforderlich ist, sollte es zusammen 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 Folgendes 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 zusammen 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]: # ({/175c9f96-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})

