跳转到主要内容

构建自定义面板选项编辑器

Grafana 插件平台提供一系列编辑器,允许用户自定义面板。标准编辑器涵盖了最常见的选项类型,如文本输入和布尔开关。如果您找不到所需的编辑器,您可以构建自己的。

面板选项编辑器基础

最简单的编辑器是一个接受两个属性的 React 组件

  • value:选项的当前值
  • onChange:更新选项的值

以下示例中的编辑器允许用户通过点击按钮切换布尔值

src/SimpleEditor.tsx
import React from 'react';
import { Button } from '@grafana/ui';
import { StandardEditorProps } from '@grafana/data';

export const SimpleEditor = ({ value, onChange }: StandardEditorProps<boolean>) => {
return <Button onClick={() => onChange(!value)}>{value ? 'Disable' : 'Enable'}</Button>;
};

要使用自定义面板选项编辑器,请在您的 module.ts 文件中使用 addCustomEditor 方法在 OptionsUIBuilder 对象上,并将 editor 属性设置为您的自定义编辑器组件的名称。

src/module.ts
export const plugin = new PanelPlugin<SimpleOptions>(SimplePanel).setPanelOptions((builder) => {
return builder.addCustomEditor({
id: 'label',
path: 'label',
name: 'Label',
editor: SimpleEditor,
});
});

向您的面板选项编辑器添加设置

您可以使用自定义编辑器来自定义多个可能的设置。要将设置添加到您的编辑器中,请将StandardEditorProps的第二个模板变量设置为包含您想要配置的设置的接口。通过item属性访问编辑器设置。

以下是一个示例编辑器,它使用一系列数字填充下拉菜单。`Settings`接口定义了`from`和`to`属性的取值范围。

src/SimpleEditor.tsx
interface Settings {
from: number;
to: number;
}

type Props = StandardEditorProps<number, Settings>;

export const SimpleEditor = ({ item, value, onChange }: Props) => {
const options: Array<SelectableValue<number>> = [];

// Default values
const from = item.settings?.from ?? 1;
const to = item.settings?.to ?? 10;

for (let i = from; i <= to; i++) {
options.push({
label: i.toString(),
value: i,
});
}

return <Select options={options} value={value} onChange={(selectableValue) => onChange(selectableValue.value)} />;
};

现在,您可以通过配置`settings`属性并调用addCustomEditor来为每个选项配置编辑器。

src/module.ts
export const plugin = new PanelPlugin<SimpleOptions>(SimplePanel).setPanelOptions((builder) => {
return builder.addCustomEditor({
id: 'index',
path: 'index',
name: 'Index',
editor: SimpleEditor,
settings: {
from: 1,
to: 10,
},
});
});

在面板选项编辑器中使用查询结果

选项编辑器可以访问上一次查询的结果。这使得您可以根据数据源返回的数据动态更新编辑器。

编辑器上下文可通过context属性访问。数据源返回的数据帧可在context.data下使用。

src/SimpleEditor.tsx
export const SimpleEditor = ({ item, value, onChange, context }: StandardEditorProps<string>) => {
const options: SelectableValue<string>[] = [];

if (context.data) {
const frames = context.data;

for (let i = 0; i < frames.length; i++) {
options.push({
label: frames[i].name,
value: frames[i].name,
});
}
}

return <Select options={options} value={value} onChange={(selectableValue) => onChange(selectableValue.value)} />;
};