☰
Metabase Embedding SDK 的 CollectionBrowser 组件:集合浏览器的 API 详解与实战指南
2026/10/11 16:18:17 网站建设 项目流程

Metabase Embedding SDK 的 CollectionBrowser 组件:集合浏览器的 API 详解与实战指南

【免费下载链接】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

CollectionBrowser 是 Metabase Embedding SDK(@metabase/embedding-sdk-react)提供的开箱即用组件,用于在宿主应用中嵌入一个可交互的集合(Collection)浏览器,展示集合及其中的仪表盘、问题、模型等内容。本文以 SDK 的 API 文档为主体,结合当前仓库的前端源码与单元测试,完整讲解CollectionBrowser的函数签名、全部 props 参数、集合 ID 定位方式、列裁剪与实体过滤,并给出可直接运行的嵌入示例与底层实现原理,帮助你快速把 Metabase 的内容浏览与导航能力集成到自己的 React 应用中。

一、组件概览:函数签名与返回值

在 API 文档 中,CollectionBrowser被定义为如下函数签名:

function CollectionBrowser(props: CollectionBrowserProps): Element;

它是一个标准 React 函数组件:

  • 参数:接收一个props对象,类型为CollectionBrowserProps,所有属性均可选。
  • 返回值:一个 ReactElement(对应官方文档中引用的 DefinitelyTyped 的 React 类型定义)。

该组件的作用是“允许你浏览集合及其中的条目”(A component that allows you to browse collections and their items),例如集合、仪表盘、保存的问题(card)、模型(dataset)等。在 SDK 的公共导出清单 中,CollectionBrowser是sdkBundleExports导出的首批组件之一,与InteractiveDashboard、InteractiveQuestion、StaticQuestion等并列,说明它是 SDK 的核心 UI 组件之一。

二、props 参数全解

CollectionBrowser的全部配置都通过CollectionBrowserProps传入。下表完整列出所有属性(继承自 API 文档的属性表,并补充了源码中的默认值与取值说明):

属性类型说明
className?string添加到根元素的自定义 CSS 类名。
collectionId?SdkBrowserCollectionId要展示的集合。可以是数字集合 ID、实体 ID 字符串、"personal"、"tenant"、"root"、"all"。默认值为"personal"。
EmptyContentComponent?ComponentType|null当集合中没有条目时展示的组件。默认null,此时渲染 SDK 内置的空状态(EmptyState)。
onClick?(item: [MetabaseCollectionItem](https://link.gitcode.com/i/e5c666b820da847a76ee28672c1bff7f)) => void点击某个条目时调用的回调函数。
pageSize?number每页展示的条目数量。默认值为 25(对应源码常量COLLECTION_PAGE_SIZE)。
showDashboardQuestions?boolean是否在集合保存的问题之外,同时展示隶属于某个仪表盘的问题。设为true时展示,默认false,保持列表聚焦于集合内容。
style?CSSProperties添加到根元素的自定义样式对象。
visibleColumns?CollectionBrowserListColumns[]集合条目表格中展示的列。不传时展示全部列。
visibleEntityTypes?("collection"|"dashboard"|"question"|"model")[]可见的实体类型。不传时展示全部实体。

这些默认值在源码中有明确印证。看 CollectionBrowser.tsx 中的组件解构:

export const CollectionBrowserInner = ({ collectionId, onClick, pageSize = COLLECTION_PAGE_SIZE, // 默认 25 visibleEntityTypes = [...USER_FACING_ENTITY_NAMES], // 默认四种实体全开 showDashboardQuestions = false, EmptyContentComponent = null, visibleColumns = COLLECTION_BROWSER_LIST_COLUMNS, // 默认列集合 className, style, }: CollectionBrowserProps) => { ... };

其中COLLECTION_PAGE_SIZE来自metabase/collections/components/CollectionContent,而USER_FACING_ENTITY_NAMES定义为["collection", "dashboard", "question", "model"](CollectionBrowser.tsx)。

此外,Props 校验由 CollectionBrowser.schema.ts 中的 Yup schema 完成:它只允许上述属性(.noUnknown()),任何未知属性都会被拒绝,这保证了宿主应用传参时的类型与运行时双重校验一致性。

三、collectionId:五种定位集合的方式

collectionId的类型是SdkBrowserCollectionId:

type SdkBrowserCollectionId = SdkCollectionId | "all";

而SdkCollectionId定义为:

type SdkCollectionId = number | "personal" | "root" | "tenant" | SdkEntityId;

其中SdkEntityId是一个字符串标记类型(type SdkEntityId = string & {};,见 SdkEntityId.md)。综合源码注释(types/collection.ts),collectionId支持以下取值:

取值含义
数字集合 ID。可以从 Metabase 实例中集合页面的 URL 里找到,例如http://localhost:3000/collection/1-my-collection中的 ID 就是1。
实体 ID 字符串例如"nT4gT_MOnU1uJ1zLsGaTV",即集合的entity_id,对内容迁移/多环境同步场景更稳定。
"personal"当前用户的个人收藏(Personal Collection)。这是默认值。
"tenant"当前用户的租户集合(Tenant Collection),面向多租户(tenants)能力。
"root"根集合,即 Metabase 的 "Our analytics"。
"all"SdkBrowserCollectionId独有的虚拟只读顶层视图,展示当前用户有权访问的一切内容,其中包含根集合、租户集合与当前用户的个人收藏。

注意:源码注释明确指出,核心应用中的CollectionId还包含"root" | "users"与"trash",但 SDK 公共 API刻意不包含这两种(types/collection.ts),这是 SDK 对外接口与内部实现的边界。

collectionId不传时的默认行为在 CollectionBrowser.tsx 中实现:

const CollectionBrowserWrapper = ({ collectionId = "personal", // 默认进入个人收藏 ...restProps }: CollectionBrowserProps) => { ... if (!collectionId) { return <CollectionNotFoundError id={collectionId} />; } return <CollectionBrowserInner collectionId={collectionId} {...restProps} />; };

四、可见实体类型与实体名映射

visibleEntityTypes控制列表中出现的实体类型,可选项为"collection"、"dashboard"、"question"、"model"。注意,这里使用的是面向用户的命名,与 Metabase 内部的model字段值并不完全一致。源码中的ENTITY_NAME_MAP(CollectionBrowser.tsx)完成了映射:

const ENTITY_NAME_MAP: Partial<Record<UserFacingEntityName, CollectionItemModel>> = { collection: "collection", dashboard: "dashboard", question: "card", // 问题在内部叫 "card" model: "dataset", // 模型在内部叫 "dataset" };

也就是说,用户在界面上看到的 "question" 在 Metabase API 中的model是"card",而 "model" 对应"dataset"。这个细节在编写onClick回调时尤其重要(见下文第六节),同时也被 SDK 的单元测试专门覆盖:onClick收到的是包含内部model值的完整条目对象(见 CollectionBrowser.unit.spec.tsx)。

五、可见列:CollectionBrowserListColumns

visibleColumns决定条目表格展示哪些列,其类型CollectionBrowserListColumns定义如下:

type CollectionBrowserListColumns = | "type" // 类型(图标列) | "name" // 名称 | "description"// 描述 | "lastEditedBy"// 最后编辑人 | "lastEditedAt"// 最后编辑时间 | "archive"; // 归档操作

不传visibleColumns时,源码默认展示以下列(CollectionBrowser.tsx):

const COLLECTION_BROWSER_LIST_COLUMNS: CollectionBrowserListColumns[] = [ "type", "name", "lastEditedBy", "lastEditedAt", "archive", ];

也就是说,默认并不包含description列,需要在visibleColumns中显式加入。这一点在单元测试中有明确断言:“默认不应包含 Description 列”“显式传入["type", "name", "description"]时才展示描述列”(见 CollectionBrowser.unit.spec.tsx)。

另一个值得注意的细节:在collectionId="all"的虚拟根视图中,合成出来的行(根集合、租户集合、个人收藏)不携带编辑信息、也不能被归档,因此lastEditedBy、lastEditedAt、archive三列会被自动过滤掉,只保留type与name(源码见 CollectionBrowser.tsx,测试见 CollectionBrowser.unit.spec.tsx)。

六、onClick 回调与 MetabaseCollectionItem

onClick在用户点击条目时触发,参数是MetabaseCollectionItem(对应源码类型 types/collection.ts):

type MetabaseCollectionItem = { collection_namespace?: string | null; description: string | null; entity_id?: SdkEntityId; id: SdkCollectionId; is_remote_synced?: boolean; "last-edit-info"?: { email: string; first_name: string | null; id: SdkUserId; last_name: string | null; timestamp: string; }; model: string; // 内部 model 名:collection / dashboard / card / dataset ... name: string; namespace?: string | null; type?: "instance-analytics" | "trash" | "remote-synced" | "library" | ... | null; };

官方示例 collection-browser-click.tsx 演示了如何利用model字段区分条目类型并切换到对应组件:

import React, { useState } from "react"; import { CollectionBrowser, InteractiveDashboard, InteractiveQuestion, type MetabaseCollectionItem, } from "@metabase/embedding-sdk-react"; export default function BrowseAndOpen() { const [dashboardId, setDashboardId] = useState<number | null>(null); const [questionId, setQuestionId] = useState<number | null>(null); const handleClick = (item: MetabaseCollectionItem) => { // Metabase 的内部命名与用户看到的不同: // question 在内部是 "card",model 在内部是 "dataset"。 if (item.model === "dashboard") { setDashboardId(item.id as number); } else if (item.model === "card" || item.model === "dataset") { setQuestionId(item.id as number); } }; if (dashboardId) { return <InteractiveDashboard dashboardId={dashboardId} />; } if (questionId) { return <InteractiveQuestion questionId={questionId} />; } return <CollectionBrowser collectionId="personal" onClick={handleClick} />; }

这段代码展示了一个典型场景:浏览 → 点击 → 在宿主应用中打开对应的InteractiveDashboard或InteractiveQuestion,把“集合浏览”与“内容展示”串成完整的数据应用体验。

注意id的类型是SdkCollectionId,即可能是数字、特殊字符串或实体 ID 字符串;当确定条目是 dashboard/card 时,示例通过as number断言后传给组件。测试用例还验证了 “Our analytics” 占位符会被映射回真实的根集合 ID"root",确保onClick与后续 API 请求拿到的都是真实 ID(见 CollectionBrowser.unit.spec.tsx)。

七、完整可运行示例

官方提供的最小可运行示例 collection-browser.tsx 如下:

import React from "react"; import { CollectionBrowser, MetabaseProvider, defineMetabaseAuthConfig, } from "@metabase/embedding-sdk-react"; const authConfig = defineMetabaseAuthConfig({ metabaseInstanceUrl: "https://your-metabase.example.com", }); export default function App() { const collectionId = 123; // 这是你想浏览的集合 ID return ( <MetabaseProvider authConfig={authConfig}> <CollectionBrowser collectionId={collectionId} pageSize={10} visibleEntityTypes={["dashboard", "question", "collection"]} /> </MetabaseProvider> ); }

要点拆解:

  • 必须包裹在MetabaseProvider中:CollectionBrowser依赖MetabaseProvider提供的认证配置(defineMetabaseAuthConfig)与全局状态。更完整的认证配置说明可参考 SDK 配置文档 与 MetabaseProviderProps。
  • collectionId={123}:直接传入数字 ID,对应 Metabase 中某个具体集合。
  • pageSize={10}:每页展示 10 条,覆盖默认的 25 条。
  • visibleEntityTypes={["dashboard", "question", "collection"]}:只展示仪表盘、问题与子集合,隐藏模型(model)。

该示例演示了最基础的嵌入方式;实际部署时还需要先完成 Embedding SDK 的认证接入(JWT / API Key / SAML),可参考 SDK 快速开始。

八、源码级实现原理

从实现上看,CollectionBrowser内部由若干层协作完成(全部位于 CollectionBrowser.tsx):

  1. 公共包装层(Public Component Wrapper):导出的CollectionBrowser通过Object.assign(withPublicComponentWrapper(...), { schema })包装(CollectionBrowser.tsx),提供加载态、错误态等统一外壳。特别注意:该组件supportsGuestEmbed: false,即不支持 Guest 嵌入模式,使用时需要带身份的用户上下文。
  2. 本地化加载:CollectionBrowserWrapper会等待 locale 加载完成(useLocale().isLocaleLoading为真时渲染SdkLoader),避免列表文案闪烁(CollectionBrowser.tsx)。
  3. 集合数据解析:useCollectionData(collectionId)负责把"personal"、"tenant"、"root"、"all"等特殊值解析为真实的内部集合 ID,并处理 403 等加载错误(CollectionBrowser.tsx)。
  4. “all” 虚拟根模式:collectionId === "all"时,组件不进入任何真实集合,而是调用useAllCollectionsItems拉取根集合、租户集合与个人收藏的列表,用ItemsTable渲染;该列表独立分页(usePagination+PaginationControls),并且面包屑会呈现一个虚拟的 “All collections” 静态入口(CollectionBrowser.tsx)。
  5. 常规集合列表:非 “all” 模式下渲染CollectionItemsTable,将pageSize、models(由visibleEntityTypes映射而来)、showDashboardQuestions、visibleColumns逐一下发(CollectionBrowser.tsx)。
  6. 面包屑导航:默认开启内部CollectionBreadcrumbs;点击子集合时通过setInternalCollectionId深入导航,并把面包屑路径与reportLocation上报同步(CollectionBrowser.tsx)。
  7. 空状态与错误状态:403 时渲染 “You don't have access to this collection” 空状态;"all"根加载失败时渲染SdkError(“Failed to load collections”)(CollectionBrowser.tsx)。

单元测试 CollectionBrowser.unit.spec.tsx 对以上行为做了系统验证,可作为理解组件行为的权威参考:

  • 默认渲染 Type / Name / Last edited by / Last edited at 四列表头(L129-L139);
  • 无个人收藏的用户(如 API Key 场景)打开"personal"时应渲染空状态,而不是请求/api/collection/undefined(L141-L166);
  • showDashboardQuestions会以show_dashboard_questions查询参数形式传给后端(L206-L216);
  • collectionId="tenant"会解析到当前用户的tenant_collection_id(L218-L246);
  • "all"模式下根集合可读则展示 “Our analytics” 行,根集合 403 时展示根下集合列表(L256-L285);
  • 虚拟根列表支持分页,且返回时页码会重置(L463-L505)。

九、使用注意事项与最佳实践

综合 API 文档、官方示例与源码测试,实际接入时建议关注以下几点:

  1. 必须登录态:CollectionBrowser不支持 Guest 嵌入(supportsGuestEmbed: false),请确保MetabaseProvider使用带身份(JWT / API Key / SAML)的认证配置。
  2. 内部 model 名与用户名词的差异:判断条目类型请以item.model的值为准(collection/dashboard/card/dataset),而不是界面语言(question / model)。
  3. 默认列不含 description:需要描述列时,显式传入visibleColumns={["type", "name", "description", ...]}。
  4. 无个人收藏的用户:API Key 用户通常没有个人收藏,默认collectionId="personal"会得到空状态而非报错,这是预期行为;也可以显式改用"root"或具体集合 ID。
  5. "all"是只读虚拟视图:其中不展示编辑信息列,适合作为“全库概览”入口。
  6. 配合其他 SDK 组件使用:onClick拿到条目后,可切换到InteractiveDashboard、InteractiveQuestion或StaticQuestion完成浏览→打开的闭环;需要更多嵌入 UI 能力可查阅 SDK 文档目录 及 组件总览。

十、小结

CollectionBrowser是 Metabase Embedding SDK 中把“集合内容浏览”能力开放给宿主应用的关键组件。通过collectionId的五种定位方式、visibleEntityTypes与visibleColumns的裁剪、pageSize分页控制,以及onClick回调与MetabaseCollectionItem的条目信息,你可以低成本地在自己的 React 应用中搭建一个与 Metabase 原生体验一致的集合导航界面,再联动InteractiveDashboard、InteractiveQuestion等组件组成完整的数据应用。其实现(CollectionBrowser.tsx)与测试(CollectionBrowser.unit.spec.tsx)展示了 SDK 在权限处理、空状态、虚拟根视图与分页等细节上的完整考量,值得在深度定制前通读。

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询