[comment]: # aside:2

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

Ta strona opisuje komponenty, których można użyć do utworzenia widoku prezentacji widżetu.
Widok prezentacji widżetu to część widżetu, która odbiera dane zgodnie z jego [konfiguracją](/configuration) i wyświetla je na pulpicie nawigacyjnym w kontenerze.

Widok prezentacji składa się z trzech części:

-  [Widget action](#widget-action)
-  [Widok widżetu](#widget-view)
-  [JavaScript](#javascript)

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

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

Klasa akcji widgetu (*WidgetView*) zawiera metody operacji na widgetach w trybie widoku prezentacji.
Większość akcji widgetów używa domyślnej klasy kontrolera *CControllerDashboardWidgetView* i/lub ją rozszerza.

Klasa akcji widgetu powinna znajdować się w katalogu *actions* i być określona w parametrze [*actions*](/devel/modules/file_structure/manifest#actions) (*actions/widget.{id}.view/class*) w pliku *manifest.json*.

**Przykład actions/WidgetView.php (zaimplementowany w natywnym widżecie Zabbix [*Informacje o systemie*](/manual/web_interface/frontend_sections/dashboards/widgets/system))**

```php
class WidgetView extends CControllerDashboardWidgetView {

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

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

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

Klasa widoku widgetu (*CWidgetView*) odpowiada za budowanie widoku prezentacji widgetu.

Klasa widoku widgetu powinna znajdować się w katalogu *views*.
Jeśli plik zawierający klasę widoku widgetu ma inną nazwę niż domyślna (*widget.view.php*), należy ją określić w parametrze [*actions*](/devel/modules/file_structure/manifest#actions) pliku *manifest.json* (*actions/widget.{id}.view/view*).

**Przykład views/widget.view.php**

```php
<?php

/**
 * Mój niestandardowy widok widgetu.
 *
 * @var CView $this
 * @var array $data
 */

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

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

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

Klasa JavaScript odpowiada za określanie zachowania widżetu, takiego jak aktualizowanie danych widżetu, zmiana rozmiaru widżetu, wyświetlanie elementów widżetu itp.

Wszystkie operacje JavaScript używają i/lub rozszerzają bazową klasę JavaScript wszystkich widżetów pulpitu - *CWidget*.
Klasa *CWidget* zawiera zestaw metod z domyślną implementacją zachowania widżetu.
W zależności od złożoności widżetu metody te mogą być używane bez zmian lub rozszerzane.

Klasa *CWidget* zawiera następujące metody:

-   Metody definiujące cykl życia widżetu: *onInitialize()*, *onStart()*, *onActivate()*, *onDeactivate()*, *onDestroy()*, *onEdit()*.
-   Metody obsługujące aktualizację i wyświetlanie danych widżetu: *promiseUpdate()*, *getUpdateRequestData()*, *processUpdateResponse(response)*, *processUpdateErrorResponse(error)*, *setContents(response)*.
-   Metody modyfikujące wygląd widżetu: *onResize()*, *hasPadding()*.

Klasa JavaScript powinna znajdować się w katalogu *assets/js* i być określona w parametrze [*assets*](/devel/modules/file_structure/manifest#assets) (*assets/js*) w pliku *manifest.json*.

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

[comment]: # ({83b2097c-be08c6bd})
##### Metody cyklu życia

Metody cyklu życia widżetu są wywoływane przez pulpit nawigacyjny oraz na różnych etapach cyklu życia widżetu podczas jego istnienia w pulpicie nawigacyjnym.

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

[comment]: # ({af2ec67e-bbc2c368})
Metoda ***onInitialize()*** definiuje początkowy stan i/lub wartości widżetu, bez wykonywania jakichkolwiek manipulacji HTML lub danymi.
Metoda ta jest wywoływana, gdy tworzony jest widżet (tworzona jest instancja obiektu widżetu), zazwyczaj poprzez dodanie widżetu do strony pulpitu nawigacyjnego lub załadowanie strony pulpitu nawigacyjnego.

Przykład:

```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})
Metoda ***onStart()*** definiuje strukturę HTML widgetu, bez wykonywania jakiejkolwiek manipulacji danymi.
Ta metoda jest wywoływana przed pierwszą aktywacją strony pulpitu, czyli zanim pulpit i jego widgety zostaną w pełni wyświetlone użytkownikowi.

Przykład:

```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})
Metoda ***onActivate()*** uaktywnia widget i czyni go interaktywnym poprzez włączenie niestandardowych detektorów zdarzeń (służących do reagowania na działania użytkownika) oraz zainicjowanie cyklu aktualizacji widgetu (aby utrzymywać jego zawartość na bieżąco).
Ta metoda jest wywoływana po aktywacji strony pulpitu, czyli gdy zostanie ona w pełni wyświetlona w interfejsie użytkownika.

Należy pamiętać, że przed wywołaniem metody *onActivate()* widget znajduje się w stanie nieaktywnym (`WIDGET_STATE_INACTIVE`).
Po pomyślnym wywołaniu widget przechodzi do stanu aktywnego (`WIDGET_STATE_ACTIVE`).
W stanie aktywnym widget reaguje na działania, nasłuchuje zdarzeń, okresowo aktualizuje swoją zawartość i może współdziałać z innymi widgetami.

Przykład:

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

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

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

[comment]: # ({4464acae-1b9abef7})
Metoda ***onDeactivate()*** zatrzymuje wszelką aktywność i interaktywność widżetu przez dezaktywację niestandardowych nasłuchiwaczy zdarzeń oraz zatrzymanie cyklu aktualizacji widżetu.
Ta metoda jest wywoływana, gdy strona pulpitu jest dezaktywowana, to znaczy po przełączeniu na inną stronę lub usunięciu, albo gdy widżet zostanie usunięty ze strony pulpitu.

Należy pamiętać, że przed wywołaniem metody *onDeactivate()* widżet znajduje się w stanie aktywnym (`WIDGET_STATE_ACTIVE`).
Po pomyślnym wywołaniu widżet przechodzi do stanu nieaktywnego (`WIDGET_STATE_INACTIVE`).

Przykład:

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

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

[comment]: # ({a26add25-06e3db00})
Metoda ***onDestroy()*** wykonuje zadania porządkowe przed usunięciem widgetu z dashboardu,
co może obejmować zamknięcie połączenia z bazą danych ustanowionego podczas inicjalizacji widgetu,
usunięcie danych tymczasowych w celu zwolnienia pamięci systemowej i uniknięcia wycieków zasobów,
wyrejestrowanie detektorów zdarzeń związanych ze zdarzeniami zmiany rozmiaru lub kliknięciami przycisków, aby zapobiec niepotrzebnej obsłudze zdarzeń i wyciekom pamięci itd.
Ta metoda jest wywoływana, gdy widget lub strona dashboardu, która go zawiera, zostaje usunięta.

Należy pamiętać, że przed wywołaniem metody *onDestroy()* widget w stanie aktywnym (`WIDGET_STATE_ACTIVE`) jest zawsze dezaktywowany przez wywołanie metody *onDeactivate()*.

Przykład:

```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})
Metoda ***onEdit()*** definiuje wygląd i zachowanie widżetu, gdy dashboard przechodzi w tryb edycji.
Ta metoda jest wywoływana, gdy dashboard przechodzi w tryb edycji, zwykle wtedy, gdy użytkownik korzysta z przycisku *Edit* widżetu lub przycisku *Edit dashboard* na dashboardzie.

Przykład:

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

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

[comment]: # ({1e54f2e8-87f28aae})
##### Metoda procesu aktualizacji

Metoda procesu aktualizacji widżetu są odpowiedzialne za pobieranie zaktualizowanych danych z serwera Zabbix lub dowolnego innego źródła danych i wyświetlanie ich w widżecie.

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

[comment]: # ({fa94eb63-c743ab46})
Metoda ***promiseUpdate()*** inicjuje proces aktualizacji danych przez pobieranie danych, zazwyczaj za pomocą żądań web lub wywołań API.
Ta metoda jest wywoływana, gdy strona pulpitu jest wyświetlana, a następnie okresowo, aż strona pulpitu zostanie przełączona na inną stronę pulpitu.

Poniżej przedstawiono przykład domyślnej implementacji metody *promiseUpdate()* używanej przez większość natywnych widgetów Zabbix.
W domyślnej implementacji metoda *promiseUpdate()* stosuje ogólny wzorzec pobierania danych z serwera.
Tworzy nowy obiekt `Curl` z odpowiednim adresem URL i parametrami żądania,
wysyła żądanie `POST` za pomocą metody *fetch()* z obiektem danych zbudowanym przez metodę *getUpdateRequestData()*,
a następnie odpowiednio przetwarza odpowiedź (lub odpowiedź błędu) za pomocą *processUpdateResponse(response)* lub *processUpdateErrorResponse(error)*.
Ta implementacja jest odpowiednia dla większości widgetów, ponieważ zazwyczaj pobierają one dane w formacie JSON i obsługują je w spójny sposób.

```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})
Metoda ***getUpdateRequestData()*** przygotowuje dane żądania do serwera na potrzeby aktualizacji widżetu, zbierając różne właściwości i odpowiadające im wartości (identyfikatory widżetu, ustawienia filtrów, zakresy czasu itp.) ze stanu i konfiguracji widżetu,
a następnie tworząc obiekt danych reprezentujący informacje wymagane do wysłania do serwera w żądaniu aktualizacji.
Ta metoda jest wywoływana wyłącznie jako część domyślnej metody *promiseUpdate()*, czyli podczas procesu aktualizacji widżetu.

Domyślna implementacja:

```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})
Metoda ***processUpdateResponse(response)*** obsługuje odpowiedź otrzymaną z serwera po żądaniu aktualizacji
i, jeśli proces aktualizacji zakończył się powodzeniem i bez błędów, czyści dane widżetu oraz wyświetla nową zawartość za pomocą metody *setContents()*.
Ta metoda jest wywoływana wyłącznie jako część domyślnej metody *promiseUpdate()*, czyli podczas procesu aktualizacji widżetu.

Domyślna implementacja:

```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})
Metoda ***processUpdateErrorResponse(error)*** obsługuje odpowiedź otrzymaną z serwera po żądaniu aktualizacji, jeśli odpowiedź zawiera błąd, i wyświetla komunikat/-y o błędzie.
Ta metoda jest wywoływana wyłącznie jako część domyślnej metody *promiseUpdate()*, czyli podczas procesu aktualizacji widżetu.

Domyślna implementacja:

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

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

[comment]: # ({31ffc8a7-8ea0452d})
Metoda ***setContents(response)*** wyświetla zawartość widżetu, jeśli proces aktualizacji widżetu zakończył się pomyślnie i bez błędów,
co może obejmować manipulowanie elementami DOM, aktualizowanie komponentów interfejsu użytkownika, stosowanie stylów lub formatowania itp.
Ta metoda jest wywoływana wyłącznie jako część domyślnej metody *processUpdateResponse(response)*, czyli podczas obsługi odpowiedzi otrzymanej z serwera po żądaniu aktualizacji.

Domyślna implementacja:

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

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

[comment]: # ({7b8ba0e6-95f750ef})
##### Metoda modyfikacji prezentacji

Metoda modyfikacji prezentacji widżetu jest odpowiedzialna za modyfikację wyglądu widżetu.

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

[comment]: # ({5e245dd6-b5613994})
Metoda ***onResize()*** odpowiada za dostosowanie elementów wizualnych widgetu do nowego rozmiaru widgetu,
co może obejmować zmianę rozmieszczenia elementów, dostosowanie wymiarów elementów, obcinanie tekstu, implementację lazy loading w celu poprawy responsywności podczas zmiany rozmiaru itp.
Ta metoda jest wywoływana, gdy widget zmienia rozmiar, na przykład gdy użytkownik ręcznie zmienia rozmiar widgetu lub gdy zmieniany jest rozmiar okna przeglądarki.

Przykład:

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

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

[comment]: # ({d22bedba-88b32413})
Metoda ***hasPadding()*** odpowiada za zastosowanie pionowego dopełnienia 8 px u dołu widżetu, gdy jest on skonfigurowany tak, aby [wyświetlać nagłówek](/manual/web_interface/frontend_sections/dashboards/widgets#common-parameters).
Ta metoda jest wywoływana po aktywowaniu strony pulpitu, czyli gdy staje się ona stroną wyświetlaną w interfejsie użytkownika.

Implementacja domyślna:

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

W przypadku niektórych widżetów konieczne jest wykorzystanie całej dostępnej przestrzeni widżetu do skonfigurowania na przykład niestandardowego koloru tła.
Poniżej przedstawiono przykład implementacji metody *hasPadding()* używanej w natywnym widżecie Zabbix [*Wartość pozycji*](/manual/web_interface/frontend_sections/dashboards/widgets/item_value).

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

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