Metabase Embedding SDK 的 EditableDashboard 组件 Props 完整指南:可编辑嵌入式仪表盘的配置与实现原理
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
EditableDashboard是 Metabase 模块化嵌入 SDK(React)中能力最完整的仪表盘组件:它具备InteractiveDashboard的全部交互能力(下钻、点击行为、查看并进入问题),同时允许终端用户在嵌入应用内直接添加/更新问题、调整卡片与布局。本文以官方 API 文档为骨架,结合当前仓库源码与示例片段,系统讲解EditableDashboard的每一个 Props 的语义、类型、默认行为与典型用法,帮助你在一屏之内完成"嵌入 → 编辑 → 保存 → 参数联动"的完整可编辑仪表盘集成。
EditableDashboard 是什么
在 docs/embedding/dashboard.md 的 "Embed an editable dashboard" 一节中,官方给出了明确定位:
EditableDashboarddoes everythingInteractiveDashboarddoes, and also lets people add and update questions, content, and the dashboard's layout.
也就是说,它是一个"交互式仪表盘 + 编辑器"的组合组件。与 Web Component(<metabase-dashboard>)不同,Web Component 没有任何属性可以开启编辑模式,因此可编辑仪表盘的唯一直接路径就是 React SDK 的EditableDashboard。组件签名定义于 docs/embedding/sdk/api/snippets/EditableDashboard.md:
function EditableDashboard(props: EditableDashboardProps): Element;- 参数:
props: EditableDashboardProps(见 docs/embedding/sdk/api/EditableDashboardProps.md) - 返回值:React
Element
从源码看,EditableDashboardProps是SdkDashboardProps & EditableDashboardOwnProps的组合类型(见 EditableDashboard.tsx),其中EditableDashboardOwnProps仅新增了dataPickerProps,其余全部继承自通用仪表盘 Props(见 SdkDashboard.tsx)。
编辑权限的前置条件
在开始编码之前,请先确认以下权限约束(均出自 docs/embedding/dashboard.md):
- 编辑要求 SSO 认证(Editing requires SSO)。
- 编辑者需要具备仪表盘所在集合(Collection)的 curate 权限;位于 usage analytics 集合中的仪表盘永远只读,与权限设置无关。
- 若仪表盘正常渲染但看不到编辑铅笔图标,说明当前查看者对该仪表盘没有写权限——可以以该用户身份检查
GET /api/dashboard/:id响应中的can_write字段。 - 多租户(tenant)场景下,发布到共享集合的仪表盘只能授予租户View权限,租户成员无法编辑这些仪表盘;但他们可以编辑自己租户集合内的仪表盘(详见 docs/embedding/tenants.md)。
基础用法
最简用法来自官方示例 editable-dashboard.tsx:用MetabaseProvider包裹认证配置,再传入dashboardId:
import React from "react"; import { EditableDashboard, MetabaseProvider, defineMetabaseAuthConfig, } from "@metabase/embedding-sdk-react"; const authConfig = defineMetabaseAuthConfig({ metabaseInstanceUrl: "https://your-metabase.example.com", }); export default function App() { const dashboardId = 1; // This is the dashboard ID you want to embed return ( <MetabaseProvider authConfig={authConfig}> <EditableDashboard dashboardId={dashboardId} /> </MetabaseProvider> ); }dashboardId是唯一必填 Props。在 EditableDashboard.schema.ts 的 Yup 校验中,dashboardId被标记为required(),其余 Props 均为可选,并且 schema 对未知属性会执行.noUnknown()严格校验——传入未定义的 Props 会在运行期校验中报错,这有助于尽早发现拼写错误。
Props 完整参考表
以下表格完整继承自 docs/embedding/sdk/api/snippets/EditableDashboardProps.md,列出EditableDashboard的全部可用 Props:
| Property | Type | Description |
|---|---|---|
autoRefreshInterval? | number | 仪表盘的自动刷新间隔,单位为秒。 |
className? | string | 添加到根元素的自定义 class 名。 |
dashboardId | string \| number | 仪表盘 ID。可以是访问仪表盘链接时的数字 ID(如http://localhost:3000/dashboard/1-my-dashboard中的1),也可以是通过 API 或 SDK Collection Browser 返回的仪表盘对象中entity_id字段的字符串 ID。 |
dataPickerProps? | Pick<SdkQuestionProps, "entityTypes"> | 当用户新建仪表盘问题时,透传给InteractiveQuestion所渲染查询构建器的额外 Props。 |
drillThroughQuestionHeight? | Height<string \| number> | 从仪表盘下钻到问题层级时,问题组件的高度。 |
drillThroughQuestionProps? | DrillThroughQuestionProps | 从仪表盘下钻到问题层级时,问题组件的 Props。 |
enableEntityNavigation? | boolean | 为true时保留内部点击行为(跳转到仪表盘/问题的链接);为false(SDK 默认值)时这些点击行为会被过滤掉。 |
hiddenParameters? | string[] | 需要隐藏的参数列表(参数隐藏机制可参考 docs/embedding/public-links.md)。注意:将initialParameters与hiddenParameters组合用于在前端过滤数据存在安全风险(详见下文);仅用于整理界面则是安全的。 |
initialParameters? | ParameterValues | 查询参数的初始值,按 slug 键控。仅在挂载时应用一次,之后用户在组件内对参数控件的修改不会回传给宿主应用。对每个参数:设为值(单选为字符串、多选为字符串数组)则应用该值;设为null则严格清除(忽略参数默认值);省略(或设为undefined)则回退到参数默认值(若无默认值则为null)。 |
onLoad? | (dashboard: MetabaseDashboard \| null) => void | 仪表盘加载完成时触发的回调。 |
onLoadWithoutCards? | (dashboard: MetabaseDashboard \| null) => void | 仪表盘加载完成但未包含卡片时触发的回调。 |
onParametersChange? | (payload: ParameterChangePayload) => void | 参数变化时触发。payload 中的source字段可区分初始状态('initial-state')、用户在 UI 中的手动修改('manual-change')以及自动更新('auto-change')。 |
onVisualizationChange? | (visualization: \| "object" \| "table" \| "bar" \| "line" \| "pie" \| "scalar" \| "row" \| "area" \| "combo" \| "pivot" \| "smartscalar" \| "gauge" \| "progress" \| "funnel" \| "map" \| "scatter" \| "boxplot" \| "waterfall" \| "sankey" \| "treemap" \| "list") => void | 当从仪表盘卡片打开问题,或用户更改问题的可视化类型时触发的回调。 |
parameters? | ParameterValues | 受控参数值,按 slug 键控。每次渲染时,该对象会整体替换仪表盘的参数值:参数设为值则使用该值;设为null则清除(即使有默认值);从对象中省略(或设为undefined)则使用默认值(若无默认值则为null)。应与onParametersChange配对使用以与用户编辑保持同步。 |
plugins? | MetabasePluginsConfig | 用于覆盖或新增下钻菜单的映射函数配置。更多细节见自定义操作(custom actions)相关章节。 |
renderDrillThroughQuestion? | () => ReactNode | 自定义 React 组件,用于渲染问题布局。可使用InteractiveQuestion的命名空间组件来构建布局。 |
style? | CSSProperties | 添加到根元素的自定义样式对象。 |
token? | string \| null | 可选令牌(从源码与 schema 看为可选属性,属于 SDK 认证机制的一部分,通常不直接传值,由 SDK 认证流程管理)。 |
withCardTitle? | boolean | 仪表盘卡片是否显示标题。 |
withDownloads? | boolean | 是否隐藏下载按钮。 |
withSubscriptions? | boolean | 是否显示订阅按钮。 |
withTitle? | boolean | 仪表盘是否显示标题。 |
参数控制三态语义:initialParameters与parameters
参数 Props 是嵌入仪表盘最常见的联动需求,官方文档给出了非常精确的三态语义,值得单独展开:
initialParameters(一次性初始值)——仅在组件挂载(mount)时应用一次,之后用户在组件内的参数控件修改不会回传给宿主应用。对每个参数:
- 设为值(单选用字符串、多选用字符串数组):应用该值;
- 设为
null:严格清除该参数,忽略参数的默认值; - 省略(或设为
undefined):回退到参数的默认值(若无默认值则为null)。
parameters(受控值)——在每次渲染时用整个对象替换仪表盘的参数值:
- 参数设为值:使用该值;
- 参数设为
null:即使有默认值也被清除; - 参数被省略(或为
undefined):使用默认值(或无默认值时为null)。
受控模式下需要与onParametersChange配对:onParametersChange回调的 payload 类型为ParameterChangePayload,其结构(见 ParameterChangePayload.md)为:
type ParameterChangePayload = { defaultParameters: ParameterValues; // 参数的默认值 lastUsedParameters: ParameterValues; // 最近一次使用的参数值 parameters: ParameterValues; // 当前参数值 source: ParameterChangeSource; // 'initial-state' | 'manual-change' | 'auto-change' };利用source可以区分"加载时的初始状态""用户在 UI 中的手动修改"与"自动更新",从而决定是否将值同步回宿主状态。
安全警告:不要在纯前端用参数过滤敏感数据
官方文档在hiddenParameters、initialParameters、parameters三个 Props 上反复强调同一条安全边界:
- 将
initialParameters(或parameters)与hiddenParameters组合,用于在前端过滤数据是安全风险:终端用户始终拥有自己的 Metabase 账号(即 SDK 的每终端用户认证模式),隐藏参数并不能阻止他们通过 API 直接访问完整数据。相关认证与安全模型见 docs/embedding/authentication.md。 - 将二者组合用于整理界面(declutter the user interface)是安全的:例如隐藏某个与当前页面无关的筛选器,只让用户看到相关控件。
从源码实现看,SdkDashboard.tsx 中hiddenParameters默认值为[],withTitle、withCardTitle默认true,withDownloads、withSubscriptions默认false,enableEntityNavigation默认false(源码注释明确写到 "SDK defaults to false (core app defaults to true)",即 SDK 出于安全考虑默认关闭实体导航,与核心应用默认开启相反)。这些默认值可以帮助你判断开箱即用的行为。
事件回调与可视化监听
EditableDashboard提供三类生命周期/交互回调:
onLoad:仪表盘(含卡片数据)加载完成后触发,参数为MetabaseDashboard | null。MetabaseDashboard是仪表盘实体对象(见 MetabaseDashboard.md),包含id、name、entity_id、collection、created_at、updated_at以及last-edit-info(最近编辑者的邮箱、姓名、ID 与时间戳)等字段。onLoadWithoutCards:仪表盘加载完成但未包含卡片时触发(例如刚创建的空仪表盘)。onParametersChange:参数变化时触发(见上文)。onVisualizationChange:当用户从仪表盘卡片打开问题、或更改某个问题的可视化类型时触发,参数为可视化类型字符串,取值包括"object"、"table"、"bar"、"line"、"pie"、"scalar"、"row"、"area"、"combo"、"pivot"、"smartscalar"、"gauge"、"progress"、"funnel"、"map"、"scatter"、"boxplot"、"waterfall"、"sankey"、"treemap"、"list"。
下钻(Drill-through)定制
从仪表盘点击卡片进入问题层级时,EditableDashboard允许通过一组 Props 定制下钻体验:
drillThroughQuestionProps:透传给下钻问题组件的 Props,类型为DrillThroughQuestionProps(完整字段见 DrillThroughQuestionProps.md),例如:entityTypes:数据选择器中可用的实体类型数组;isSaveEnabled/onSave/onBeforeSave:是否显示保存按钮及保存前后回调;onRun:问题更新(包括点击编辑器中的 Visualize 按钮)时触发;initialCollection/targetCollection:保存弹窗中预选的集合(targetCollection会隐藏集合选择器);withAlerts、withDownloads、withChartTypeSelector、withEditorButton:各项功能开关;dataPicker:数据源选择方式,可设为"staged"使用完整数据选择器;height/width/style/className:尺寸与样式。
drillThroughQuestionHeight:下钻问题组件的高度,接受 CSS 尺寸值(数字或字符串)。renderDrillThroughQuestion:完全自定义下钻问题的布局渲染函数,返回任意ReactNode。官方建议使用InteractiveQuestion的命名空间子组件来搭建布局(详见 docs/embedding/question-reference.md 中 "customize the layout of an interactive chart" 一节)。plugins:类型为MetabasePluginsConfig,用于覆盖或新增下钻菜单(点击图表后出现的自定义菜单项)。在 EditableDashboard.tsx 中可以看到,drillThroughQuestionProps?.plugins会被提取出来,与 SDK 内部导航一起通过getEmbeddingMode/createEmbeddingSdkMode组装成clickActionMode,再传给底层仪表盘渲染——这就是"点击图表 → 自定义菜单"的底层实现链路。
另外,卡片右上角的溢出菜单(下载结果、编辑问题等操作)可以通过dashboardCardMenu插件定制,见 docs/embedding/dashboard.md。
编辑模式与仪表盘动作的源码实现
阅读 EditableDashboard.tsx 可以确认"可编辑"这一能力的实现方式:
- 动作按钮按编辑状态切换:
dashboardActions函数根据isEditing决定工具栏渲染哪些动作。非编辑状态只显示EDIT_DASHBOARD(编辑铅笔)、DASHBOARD_SUBSCRIPTIONS(订阅)、DOWNLOAD_PDF(下载 PDF)与REFRESH_INDICATOR(刷新指示);进入编辑状态后则展开完整的DASHBOARD_EDITING_ACTIONS动作集(保存、取消、添加问题/文本/筛选器等)。 - 内部导航:组件用
SdkInternalNavigationProvider包裹,并通过useSdkInternalNavigation的push实现 SDK 内部的仪表盘/问题跳转;enableEntityNavigation控制这些内部点击行为是否保留。 - SDK 统计埋点:组件挂载时会调用
useTrackSdkComponentMount("EditableDashboard", ...)记录with_title、with_downloads、with_subscriptions、auto_refresh、enable_entity_navigation等配置。
底层所有仪表盘 Props 的统一默认值、参数受控逻辑与加载事件处理都在 SdkDashboard.tsx 中实现,EditableDashboard只是叠加了编辑动作与查询构建器透传(dataPickerProps)。组件还挂载了schema属性(EditableDashboard.schema),用于运行时 Props 校验(见 EditableDashboard.schema.ts)。
典型场景示例
场景一:限定新建问题时可选的数据源
当用户在编辑模式下添加新问题,EditableDashboard会打开查询构建器。通过dataPickerProps的entityTypes可限制数据选择器中的实体类型,可选值为"table"、"question"、"model"。例如只允许用户基于表格构建,避免他们使用其他人保存的问题(官方示例 editable-dashboard-data-picker.tsx):
import React from "react"; import { EditableDashboard } from "@metabase/embedding-sdk-react"; export default function TablesOnlyDashboard() { const dashboardId = 1; // This is the dashboard ID you want to embed return ( <EditableDashboard dashboardId={dashboardId} dataPickerProps={{ entityTypes: ["table"] }} /> ); }场景二:自定义容器高度
通过style传入 CSS 样式对象控制根元素尺寸(官方示例 custom-height.tsx):
import { EditableDashboard } from "@metabase/embedding-sdk-react"; const dashboardId = 1; const Example = () => ( <EditableDashboard style={{ height: 800, minHeight: "auto", }} dashboardId={dashboardId} /> );场景三:创建新仪表盘并交给 EditableDashboard
在宿主应用中让用户先创建一个空仪表盘,再交给EditableDashboard填充内容,官方提供了两种途径(见 docs/embedding/dashboard.md 与示例 create-dashboard.tsx):
方式 A:useCreateDashboardApihook(完全自定义 UI)
const hookResult = useCreateDashboardApi(); const handleDashboardCreate = async () => { // hookResult 在 SDK 完全加载并初始化之前为 null if (!hookResult) { return; } const dashboard = await hookResult.createDashboard({ name: "New dashboard", description: null, collectionId: 1, }); // 用创建好的空仪表盘去驱动 EditableDashboard,例如 setState 后渲染 };方式 B:CreateDashboardModal组件(使用 Metabase 自带弹窗)
const [dashboard, setDashboard] = useState<MetabaseDashboard | null>(null); if (dashboard) { return <EditableDashboard dashboardId={dashboard.id} />; } return <CreateDashboardModal onClose={handleClose} onCreate={setDashboard} />;使用限制与注意事项
- 同一页面目前只能渲染一个仪表盘组件:官方明确说明 React SDK 尚不支持同一页面同时放置两个仪表盘组件,
StaticDashboard、InteractiveDashboard、EditableDashboard均受此限制(见 docs/embedding/dashboard.md 附近说明)。 - Web Component 无编辑属性:
<metabase-dashboard>没有开启编辑的属性。若必须在非 React 应用提供编辑能力,可退而使用集合浏览器<metabase-browser initial-collection="123" read-only="false">,它会为每个打开的仪表盘附带编辑铅笔图标并增加 "New dashboard" 按钮;代价是用户需要通过集合导航找到仪表盘(详见 docs/embedding/dashboard.md)。 - 仪表盘 ID 的两种形态:既可以是 URL 中的数字 ID,也可以是
entity_id字符串。企业版(Pro/Enterprise)下entity_id在序列化迁移(如从 staging 到 production)后保持不变,更适合作为稳定标识(见 docs/embedding/dashboard-reference.md)。 - 前端参数过滤≠数据安全:任何需要"按用户过滤数据"的需求都必须依赖 Metabase 的行级权限、SSO 用户映射等后端机制,而不是
hiddenParameters加参数的组合。 - 编辑权限取决于集合权限:确保查看者对该仪表盘所在集合拥有 curate 权限,否则编辑入口不会出现。
延伸阅读
- 组件与 Props 的 HTML 版参考:EditableDashboard.html、EditableDashboardProps.html
- 仪表盘组件全家桶 Props 参考:docs/embedding/dashboard-reference.md
- 嵌入仪表盘完整教程:docs/embedding/dashboard.md
- 组件源码实现:EditableDashboard.tsx、SdkDashboard.tsx
- Props 运行期校验 schema:EditableDashboard.schema.ts
- 下钻问题组件 Props:DrillThroughQuestionProps.md
- SDK 认证与安全模型:docs/embedding/authentication.md
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考