[comment]: # translation:outdated

[comment]: # aside:2

[comment]: # ({49595c0a-680e771f})
# Презентация

На этой странице описаны компоненты, которые можно использовать для создания представления виджета.
Представление виджета - это часть виджета, которая получает данные в соответствии со своей [конфигурацией](/configuration) и отображает их на информационной панели в контейнере.

Представление презентации состоит из трех частей:

- [Действие виджета](#widget-action)
- [Просмотр виджета](#widget-view)
- [JavaScript](#javascript)

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

[comment]: # ({12d91455-59d8ff17})
### Действие виджета

Класс действий виджета (*WidgetView*) содержит методы для работы с виджетами в режиме просмотра презентации.
Большинство действий виджетов используют и/или расширяют класс контроллера по умолчанию *CControllerDashboardWidgetView*.

Класс действия виджета должен находиться в каталоге *actions* и указываться в параметре [*actions*](/devel/modules/file_structure/manifest#actions) (*actions/widget.{id}.view/class*) в файле *manifest.json*.

**Пример actions/WidgetView.php (реализован в родном для Zabbix виджете [*Информация о системе*](/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})
### Виджет

Класс представления виджета (*CWidgetView*) отвечает за построение представления виджета.

Класс представления виджета должен находиться в каталоге *views*.
Если файл, содержащий класс представления виджета, имеет имя, отличное от имени по умолчанию (*widget.view.php*), то его необходимо указать в файле *manifest.json* [*actions*](/devel/modules/file_structure/manifest#actions) параметр (*actions/widget.{id}.view/view*).

**пример views/widget.view.php**

```php
<?php

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

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

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

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

Класс JavaScript отвечает за определение поведения виджета, например, обновление данных виджета, изменение размера виджета, отображение элементов виджета и т. д.

Все операции JavaScript используют и/или расширяют базовый класс JavaScript всех виджетов панели - *CWidget*.
Класс *CWidget* содержит набор методов с реализацией по умолчанию для поведения виджета.
В зависимости от сложности виджета эти методы можно использовать как есть или расширить.

Класс *CWidget* содержит следующие методы:

- Методы, определяющие жизненный цикл виджета: *onInitialize()*, *onStart()*, *onActivate()*, *onDeactivate()*, *onDestroy()*, *onEdit()*.
- Методы, обрабатывающие обновление и отображение данных виджета: *promiseUpdate()*, *getUpdateRequestData()*, *processUpdateResponse(response)*, *processUpdateErrorResponse(error)*, *setContents(response)*.
- Методы, изменяющие внешний вид виджета: *onResize()*, *hasPadding()*.

Класс JavaScript должен находиться в каталоге *assets/js* и указываться в параметре [*assets*](/devel/modules/file_structure/manifest#assets) (*assets/js*) в *manifest.json* файл.

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

[comment]: # ({83b2097c-be08c6bd})
##### Методы жизненного цикла

Методы жизненного цикла виджета вызываются панелью и на разных этапах жизненного цикла виджета во время его существования на панели.

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

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

Метод ***onInitialize()*** определяет исходное состояние и/или значения виджета без выполнения каких-либо манипуляций с HTML или данными.
Этот метод вызывается при создании виджета (создается экземпляр объекта виджета), обычно путем добавления виджета на страницу панели или загрузки страницы панели.

Пример:

```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})

Метод ***onStart()*** определяет HTML-структуру виджета, не выполняя никаких манипуляций с данными.
Этот метод вызывается перед первой активацией страницы панели мониторинга, то есть до того, как панель мониторинга и ее виджеты полностью отобразятся пользователю.

Пример:

```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})

Метод ***onActivate()*** делает виджет активным и интерактивным, включая настраиваемые прослушиватели событий (для реагирования на действия пользователя) и запуская цикл обновления виджета (для поддержания актуальности его содержимого).
Этот метод вызывается при активации страницы информационной панели, то есть когда она полностью отображается в пользовательском интерфейсе.

Обратите внимание, что до вызова метода *onActivate()* виджет находится в неактивном состоянии («WIDGET_STATE_INACTIVE»).
После успешного вызова виджет переходит в активное состояние («WIDGET_STATE_ACTIVE»).
В активном состоянии виджет реагирует, слушает события, периодически обновляет свое содержимое и может взаимодействовать с другими виджетами.

Пример:

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

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

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

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

Метод ***onDeactivate()*** останавливает любую активность и интерактивность виджета, деактивируя пользовательские прослушиватели событий и останавливая цикл обновления виджета.
Этот метод вызывается, когда страница панели деактивируется, то есть отключается или удаляется, или когда виджет удаляется со страницы панели.

Обратите внимание, что до вызова метода *onDeactivate()* виджет находится в активном состоянии (`WIDGET_STATE_ACTIVE`).
После успешного вызова виджет переходит в неактивное состояние («WIDGET_STATE_INACTIVE»).

Пример:

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

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

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

Метод ***onDestroy()*** выполняет задачи очистки перед удалением виджета с панели управления,
что может включать в себя закрытие соединения с базой данных, которое было установлено во время инициализации виджета, очистка временных данных для освобождения системной памяти и предотвращения утечек ресурсов,
отмена регистрации прослушивателей событий, связанных с событиями изменения размера или нажатиями кнопок, чтобы предотвратить ненужную обработку событий и утечки памяти и т. д.
Этот метод вызывается при удалении виджета или страницы информационной панели, которая его содержит.

Обратите внимание, что перед вызовом метода *onDestroy()* виджет в активном состоянии (`WIDGET_STATE_ACTIVE`) всегда деактивируется с помощью вызова метода *onDeactivate()*.

Пример:

```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})

Метод ***onEdit()*** определяет внешний вид и поведение виджета при переходе панели управления в режим редактирования.
Этот метод вызывается, когда панель мониторинга переходит в режим редактирования, обычно когда пользователь взаимодействует с кнопкой *Редактировать* виджета или кнопкой *Редактировать панель* панели мониторинга.

Пример:

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

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

[comment]: # ({1e54f2e8-87f28aae})
##### Методы обновления виджета

Методы процесса обновления виджета отвечают за получение обновленных данных с сервера Zabbix или любого другого источника данных и их отображение в виджете.

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

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

Метод ***promiseUpdate()*** инициирует процесс обновления данных путем получения данных, обычно с помощью веб-запросов или вызовов API.
Этот метод вызывается при отображении страницы панели и периодически после этого, пока страница панели не переключится на другую страницу панели.

Ниже приведен пример реализации по умолчанию метода *promiseUpdate()*, используемого большинством родных виджетов Zabbix.
В реализации по умолчанию метод *promiseUpdate()* соответствует общему шаблону получения данных с сервера.
Он создает новый объект Curl с соответствующим URL-адресом и параметрами запроса,
отправляет запрос POST с помощью метода *fetch()* с объектом данных, созданным методом *getUpdateRequestData()*,
и обрабатывает ответ (или ответ об ошибке) с помощью *processUpdateResponse(response)* или *processUpdateErrorResponse(error)* соответственно.
Эта реализация подходит для большинства виджетов, поскольку они обычно получают данные в формате JSON и обрабатывают их согласованным образом.

```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})

Метод ***getUpdateRequestData()*** подготавливает данные запроса сервера для обновления виджета, собирая различные свойства и соответствующие им значения (идентификаторы виджета, настройки фильтра, временные диапазоны и т. д.) из состояния и конфигурации виджета, и создание объекта данных, который представляет необходимую информацию, подлежащую отправке на сервер в запросе на обновление.
Этот метод вызывается только как часть метода *promiseUpdate()* по умолчанию, то есть во время процесса обновления виджета.

Реализация по умолчанию:

```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})

Метод ***processUpdateResponse(response)*** обрабатывает ответ, полученный от сервера после запроса на обновление,
и, если процесс обновления прошел успешно и без ошибок, очищает данные виджета и отображает новое содержимое с помощью метода *setContents()*.
Этот метод вызывается только как часть метода *promiseUpdate()* по умолчанию, то есть во время процесса обновления виджета.

Реализация по умолчанию:

```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})

Метод ***processUpdateErrorResponse(error)*** обрабатывает ответ, полученный от сервера после запроса на обновление, если ответ является ошибкой, и отображает сообщения об ошибках.
Этот метод вызывается только как часть метода *promiseUpdate()* по умолчанию, то есть во время процесса обновления виджета.

Реализация по умолчанию:

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

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

[comment]: # ({31ffc8a7-8ea0452d})
Метод ***setContents(response)*** отображает содержимое виджета, если процесс обновления виджета прошел успешно и без ошибок, что может включать в себя манипулирование элементами DOM, обновление компонентов пользовательского интерфейса, применение стилей или форматирования и т. д.
Этот метод вызывается только как часть метода *processUpdateResponse(response)* по умолчанию, то есть в процессе обработки ответа, полученного от сервера после запроса на обновление.

Реализация по умолчанию:

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

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

[comment]: # ({7b8ba0e6-95f750ef})
##### Методы модификации представления

Методы модификации представления виджета отвечают за изменение внешнего вида виджета.

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

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

Метод ***onResize()*** отвечает за настройку визуальных элементов виджета в соответствии с новым размером виджета,
которые могут включать перестановку элементов, настройку размеров элементов, усечение текста, реализацию отложенной загрузки для улучшения реагирования при изменении размера и т. д.
Этот метод вызывается при изменении размера виджета, например, когда пользователь вручную изменяет размер виджета или когда изменяется размер окна браузера.

Пример:

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

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

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

Метод ***hasPadding()*** отвечает за применение вертикального заполнения шириной 8 пикселей в нижней части виджета, когда он настроен на [показ заголовка](/manual/web_interface/frontend_sections/dashboards/widgets#common-parameters).
Этот метод вызывается, когда страница информационной панели активируется, то есть когда она становится отображаемой страницей в пользовательском интерфейсе.

Реализация по умолчанию:

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

Для некоторых виджетов необходимо использовать все доступное пространство виджетов, например, для настройки собственного цвета фона.
Ниже приведен пример реализации метода *hasPadding()*, используемого в родном для Zabbix виджете [*значение элемента данных*](/manual/web_interface/frontend_sections/dashboards/widgets/item_value).

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

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