这是原厂英文文档的翻译页面. 欢迎帮助我们 完善文档.
2022 Zabbix中国峰会
2022 Zabbix中国峰会

Presentation

Widget presentation is part of the widget module that receives the data according to the configuration and displays it on the dashboard in а container. Widget presentation container can be positioned and resized.

The widget view consists of two optional parts:

Widget actions

The majority of widget actions use and/or extend the default controller class CControllerDashboardWidgetView. This class contains methods for operations with widgets in the view mode.

The class source file must be located in the actions directory and must be specified as an action class in the manifest.json in the actions/widget.{id}.view/class section.

For example, this is how extending the default class is implemented in the Zabbix-native widget System information:

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()
                   ]
               ]));
           }
       }

Widget view

Widget presentation view is being built by class CWidgetView.

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

The widget's view file should be located in the views directory. If the file has a default name widget.view.php, there is no need to register it in the manifest.json. If the file has a different name, specify it in the actions/widget.{id}.view/view section of manifest.json.

JavaScript

JavaScript 类负责确定仪表盘小部件的行为,如更新小部件数据、调整小部件大小、显示小部件元素等。

所有 JavaScript 操作都使用和/或扩展了所有仪表盘小部件的基础 JavaScript 类 - CWidgetCWidget 类包含一组具有默认实现的小部件行为方法。 根据小部件的复杂性,这些方法可以直接使用或进行扩展。

CWidget 类包含以下方法:

  • 定义小部件生命周期的方法:onInitialize()onStart()onActivate()onDeactivate()onDestroy()onEdit()
  • 处理更新和显示小部件数据的方法:promiseUpdate()getUpdateRequestData()processUpdateResponse(response)processUpdateErrorResponse(error)setContents(response)
  • 修改小部件外观的方法:onResize()hasPadding()

JavaScript 类应位于 assets/js 目录中,并在 manifest.json 文件的 assets (assets/js) 参数中指定。

Lifecycle methods

The widget lifecycle methods are invoked by the dashboard, and at different stages of the widget's lifecycle during its existence within the dashboard.

onInitialize() 方法定义了仪表盘的初始状态和/或值,但不执行任何HTML或数据操作。 此方法在创建仪表盘(实例化仪表盘对象)时被调用,通常是通过将仪表盘添加到仪表盘页面或加载仪表盘页面来完成的。

示例:

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;
       }

onStart() 方法定义了仪表盘的HTML结构,但不执行任何数据操作。 此方法在仪表盘页面首次激活之前被调用,即在仪表盘及其仪表盘完全显示给用户之前。

示例:

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

The _doActivate() method makes the widget active and interactive by enabling custom event listeners (for responding to user actions) and initiating the widget update cycle (for keeping its content up-to-date). This method is invoked when the dashboard page is activated, that is, when it becomes fully displayed in the user interface.

Note that before the _doActivate() method is invoked, the widget is in the inactive state (WIDGET_STATE_INACTIVE). After successful invocation, the widget transitions to the active state (WIDGET_STATE_ACTIVE). In the active state, the widget is responsive, listens to events, updates its content periodically, and can interact with other widgets.

Example:

_doActivate() {
           super._doActivate();
       
           if (this._has_contents) {
               this._activateContentsEvents();
           }
       }

The _doDeactivate() method stops any activity and interactivity of the widget by deactivating custom event listeners and stopping the widget update cycle. This method is invoked when the dashboard page is deactivated, that is, switched away or deleted, or when the widget is deleted from the dashboard page.

Note that before the _doDeactivate() method is invoked, the widget is in the active state (WIDGET_STATE_ACTIVE). After successful invocation, the widget transitions to the inactive state (WIDGET_STATE_INACTIVE).

Example:

_doDeactivate() {
           super._doDeactivate();
       
           this._deactivateContentsEvents();
       }

The _doDestroy() method performs cleanup tasks before the widget is deleted from the dashboard, which can include closing a database connection that was established during widget initialization, cleaning up temporary data to free up system memory and avoid resource leaks, unregistering event listeners related to resize events or button clicks to prevent unnecessary event handling and memory leaks, etc. This method is invoked when the widget or the dashboard page that contains it is deleted.

Note that before the _doDestroy() method is invoked, a widget in an active state (WIDGET_STATE_ACTIVE) is always deactivated with the invocation of the _doDeactivate() method.

Example:

_doDestroy() {
           super._doDestroy();
       
           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);
           }
       }

The setEditMode() method defines the appearance and behavior of the widget when the dashboard transitions into editing mode. This method is invoked when the dashboard transitions into editing mode, typically when a user interacts with the widget's Edit button or the dashboard's Edit dashboard button.

Example:

setEditMode() {
           if (this._has_contents) {
               this._deactivateContentsEvents();
               this._removeTree();
           }
       
           super.setEditMode();
       
           if (this._has_contents && this._state === WIDGET_STATE_ACTIVE) {
               this._makeTree();
               this._activateTree();
               this._activateContentsEvents();
           }
       }
Update process methods

The widget update process methods are responsible for retrieving updated data from Zabbix server or any other data source and displaying it in the widget.

The _promiseUpdate() method initiates the data update process by retrieving data, typically using web requests or API calls. This method is invoked when a dashboard page is displayed and periodically after, until the dashboard page is switched to another dashboard page.

The following is an example of the default implementation of the _promiseUpdate() method used by most Zabbix-native widgets. In the default implementation, the _promiseUpdate() method follows a general pattern for retrieving data from the server. It creates a new Curl object with the appropriate URL and request parameters, sends a POST request using the fetch() method with the data object constructed by the _getUpdateRequestData() method, and processes the response (or an error response) with the _processUpdateResponse(response) or _processUpdateErrorResponse(error) accordingly. This implementation is suitable for most widgets as they typically retrieve data in a JSON format and handle it in a consistent manner.

_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);
               });
       }

The _getUpdateRequestData() method prepares the server request data for updating the widget by gathering various properties and their corresponding values (widget identifiers, filter settings, time ranges, etc.) from the widget's state and configuration, and constructing a data object that represents the necessary information to be sent to the server in the update request. This method is invoked only as part of the default [_promiseUpdate()] method, that is, during the widget update process.

Default implementation:

_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._content_size
           };
       }

The _processUpdateResponse(response) method handles the response received from the server after the update request, and, if the update process has been successful and without errors, clears widget data and displays new contents with the _setContents() method. This method is invoked only as part of the default _promiseUpdate() method, that is, during the widget update process.

Default implementation:

_processUpdateResponse(response) {
           this._setContents({
               name: response.name,
               body: response.body,
               messages: response.messages,
               info: response.info,
               debug: response.debug
           });
       }

The _processUpdateErrorResponse(error) method handles the response received from the server after the update request if the response is an error, and displays the error message/-s. This method is invoked only as part of the default _promiseUpdate() method, that is, during the widget update process.

Default implementation:

_processUpdateErrorResponse(error) {
           this._setErrorContents({error});
       }
       
       _setErrorContents({error}) {
           const message_box = makeMessageBox('bad', error.messages, error.title)[0];
       
           this._content_body.innerHTML = '';
           this._content_body.appendChild(message_box);
       
           this._removeInfoButtons();
       }

The _setContents() method displays widget contents if the widget update process has been successful and without errors, which can include manipulating DOM elements, updating UI components, applying styles or formatting, etc. This method is invoked only as part of the default _processUpdateResponse(response) method, that is, during the process of handling the response received from the server after the update request.

Default implementation:

_setContents({name, body, messages, info, debug}) {
           this._setHeaderName(name);
       
           this._content_body.innerHTML = '';
       
           if (messages !== undefined) {
               const message_box = makeMessageBox('bad', messages)[0];
       
               this._content_body.appendChild(message_box);
           }
       
           if (body !== undefined) {
               this._content_body.insertAdjacentHTML('beforeend', body);
           }
       
           if (debug !== undefined) {
               this._content_body.insertAdjacentHTML('beforeend', debug);
           }
       
           this._removeInfoButtons();
       
           if (info !== undefined) {
               this._addInfoButtons(info);
           }
       }
Presentation modification methods

The widget presentation modification methods are responsible for modifying widget appearance.

The resize() method is responsible for adjusting widget's visual elements to accommodate the new widget size, which can include rearranging elements, adjusting element dimensions, text truncation, implementing lazy loading to improve responsiveness during resizing, etc. This method is invoked when the widget is resized, for example, when the user manually resizes the widget or when the browser window is resized.

Example:

resize() {
           if (this._state === WIDGET_STATE_ACTIVE) {
               this._startUpdating();
           }
       }

The _hasPadding() method is responsible for applying an 8px vertical padding at the bottom of the widget when it is configured to show its header. This method is invoked when the dashboard page is activated, that is, when it becomes the displayed page in the user interface.

Default implementation:

_hasPadding() {
           return this._view_mode !== ZBX_WIDGET_VIEW_MODE_HIDDEN_HEADER;
       }

For some widgets it is necessary to use all of the available widget space to configure, for example, a custom background color. The following is an example of the implementation of the _hasPadding() method used in the Zabbix-native Item value widget.

_hasPadding() {
           return false;
       }