关于 umbraco-picker-data-source
这是面向 Umbraco 开发者的技能,用于为选择器属性编辑器创建数据源。它帮助定义数据获取、搜索和树形或集合展示,并生成相应清单与数据源类。
主要功能
- 01创建树形或集合数据源
- 02定义数据获取和搜索
- 03配置可选项目筛选
- 04生成清单和数据源类
适用场景
- 01从外部 API 提供选择项
- 02构建带搜索的树形选择器
- 03为属性编辑器筛选现有内容
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ umbraco/ umbraco-cms-backoffice-skills --skill umbraco-picker-data-source安装后在 Claude Code 中输入/umbraco-picker-data-source确认已加载。
详细介绍
Umbraco Picker Data Source
这是什么?
Picker Data Source 为基于选择器的属性编辑器提供数据。它允许你创建自定义数据源,为内容选择器提供条目,并定义如何获取、搜索和以树形或集合形式显示条目。这适用于创建从自定义实体、外部 API 或现有内容的筛选子集中进行选择的选择器。
文档
实现前,请务必获取最新文档:
- Foundation:https://docs.umbraco.com/umbraco-cms/extend-your-project/backoffice-extensions/foundation
- Extension Registry:https://docs.umbraco.com/umbraco-cms/extend-your-project/backoffice-extensions/extending-overview/extension-registry
- Property Editors:https://docs.umbraco.com/umbraco-cms/extend-your-project/backoffice-extensions/property-editors
参考示例
Umbraco 源码包含可运行的示例:
位置:/Umbraco-CMS/src/Umbraco.Web.UI.Client/examples/picker-data-source/
此示例演示了多种 Picker Data Source 实现:
- 自定义集合选择器
- 带搜索功能的自定义树形选择器
- 配置起始节点的文档选择器
- 媒体、语言、Webhook 和用户选择器
相关 Foundation 技能
-
Repository Pattern:用于数据获取模式
- 参考技能:
umbraco-repository-pattern
- 参考技能:
-
Tree:用于基于树的 Picker Data Source
- 参考技能:
umbraco-tree
- 参考技能:
工作流
- 获取文档 - 对上述 URL 使用 WebFetch
- 提问 - 要选择什么数据?使用树形还是集合?是否需要搜索?有哪些配置选项?
- 生成文件 - 根据最新文档创建 manifest 和数据源类
- 说明 - 展示创建的内容,以及如何与属性编辑器搭配使用
Manifest 示例
import { UMB_PICKER_DATA_SOURCE_TYPE } from '@umbraco-cms/backoffice/picker-data-source';
export const manifests: Array<UmbExtensionManifest> = [
{
type: 'propertyEditorDataSource',
dataSourceType: UMB_PICKER_DATA_SOURCE_TYPE,
alias: 'My.PropertyEditorDataSource.CustomPicker',
name: 'Custom Picker Data Source',
api: () => import('./my-picker-data-source.js'),
meta: {
label: 'Custom Items',
icon: 'icon-list',
description: 'Pick from custom items',
},
},
];
树形选择器数据源
用于具有父子关系的层级数据:
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import type {
UmbPickerSearchableDataSource,
UmbPickerTreeDataSource,
} from '@umbraco-cms/backoffice/picker-data-source';
import type { UmbSearchRequestArgs, UmbSearchResultItemModel } from '@umbraco-cms/backoffice/search';
import type { UmbTreeChildrenOfRequestArgs, UmbTreeItemModel } from '@umbraco-cms/backoffice/tree';
export class MyPickerTreeDataSource
extends UmbControllerBase
implements UmbPickerTreeDataSource, UmbPickerSearchableDataSource
{
// Filter function to determine which items can be picked
treePickableFilter: (treeItem: UmbTreeItemModel) => boolean = (treeItem) =>
!!treeItem.unique && treeItem.entityType === 'my-entity';
searchPickableFilter: (searchItem: UmbSearchResultItemModel) => boolean = (searchItem) =>
!!searchItem.unique && searchItem.entityType === 'my-entity';
// Return the root node (container for all items)
async requestTreeRoot() {
return {
data: {
unique: null,
name: 'My Items',
icon: 'icon-folder',
hasChildren: true,
entityType: 'my-entity-root',
isFolder: true,
},
};
}
// Return items at the root level
async requestTreeRootItems() {
const rootItems = myItems.filter((item) => item.parent.unique === null);
return {
data: {
items: rootItems,
total: rootItems.length,
},
};
}
// Return children of a specific item
async requestTreeItemsOf(args: UmbTreeChildrenOfRequestArgs) {
const items = myItems.filter(
(item) =>
item.parent.entityType === args.parent.entityType &&
item.parent.unique === args.parent.unique
);
return {
data: {
items: items,
total: items.length,
},
};
}
// Return ancestors for breadcrumb navigation
async requestTreeItemAncestors() {
return { data: [] };
}
// Return specific items by their unique IDs
async requestItems(uniques: Array<string>) {
const items = myItems.filter((x) => uniques.includes(x.unique));
return { data: items };
}
// Search items by query string
async search(args: UmbSearchRequestArgs) {
const result = myItems.filter((item) =>
item.name.toLowerCase().includes(args.query.toLowerCase())
);
return {
data: {
items: result,
total: result.length,
},
};
}
}
export { MyPickerTreeDataSource as api };
// Sample data
const myItems: Array<UmbTreeItemModel> = [
{
unique: '1',
entityType: 'my-entity',
name: 'Item 1',
icon: 'icon-document',
parent: { unique: null, entityType: 'my-entity-root' },
isFolder: false,
hasChildren: false,
},
{
unique: '2',
entityType: 'my-entity',
name: 'Item 2',
icon: 'icon-document',
parent: { unique: null, entityType: 'my-entity-root' },
isFolder: false,
hasChildren: false,
},
];
集合选择器数据源
用于没有层级结构的平面列表:
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import type { UmbPickerCollectionDataSource } from '@umbraco-cms/backoffice/picker-data-source';
import type { UmbCollectionItemModel } from '@umbraco-cms/backoffice/collection';
export class MyPickerCollectionDataSource
extends UmbControllerBase
implements UmbPickerCollectionDataSource
{
async requestCollection() {
const items: UmbCollectionItemModel[] = [
{ unique: '1', entityType: 'my-entity', name: 'Item 1', icon: 'icon-document' },
{ unique: '2', entityType: 'my-entity', name: 'Item 2', icon: 'icon-document' },
{ unique: '3', entityType: 'my-entity', name: 'Item 3', icon: 'icon-document' },
];
return {
data: {
items,
total: items.length,
},
};
}
async requestItems(uniques: Array<string>) {
// Return specific items by unique IDs
const allItems = await this.requestCollection();
const items = allItems.data.items.filter((x) => uniques.includes(x.unique));
return { data: items };
}
}
export { MyPickerCollectionDataSource as api };
带配置的数据源
为 Picker Data Source 添加设置:
export const manifests: Array<UmbExtensionManifest> = [
{
type: 'propertyEditorDataSource',
dataSourceType: UMB_PICKER_DATA_SOURCE_TYPE,
alias: 'My.PropertyEditorDataSource.ConfigurablePicker',
name: 'Configurable Picker Data Source',
api: () => import('./my-configurable-picker-data-source.js'),
meta: {
label: 'Configurable Items',
icon: 'icon-settings',
description: 'Pick items with configuration options',
settings: {
properties: [
{
alias: 'startNode',
label: 'Start Node',
description: 'Select where to start picking from',
propertyEditorUiAlias: 'Umb.PropertyEditorUi.ContentPicker.Source',
},
{
alias: 'filter',
label: 'Filter Types',
description: 'Select which types can be picked',
propertyEditorUiAlias: 'Umb.PropertyEditorUi.ContentPicker.SourceType',
},
],
},
},
},
];
接口
interface UmbPickerTreeDataSource {
treePickableFilter?: (treeItem: UmbTreeItemModel) => boolean;
requestTreeRoot(): Promise<{ data: UmbTreeItemModel }>;
requestTreeRootItems(): Promise<{ data: { items: UmbTreeItemModel[]; total: number } }>;
requestTreeItemsOf(args: UmbTreeChildrenOfRequestArgs): Promise<{ data: { items: UmbTreeItemModel[]; total: number } }>;
requestTreeItemAncestors(): Promise<{ data: UmbTreeItemModel[] }>;
requestItems(uniques: string[]): Promise<{ data: UmbTreeItemModel[] }>;
}
interface UmbPickerSearchableDataSource {
searchPickableFilter?: (searchItem: UmbSearchResultItemModel) => boolean;
search(args: UmbSearchRequestArgs): Promise<{ data: { items: UmbSearchResultItemModel[]; total: number } }>;
}
interface UmbPickerCollectionDataSource {
requestCollection(): Promise<{ data: { items: UmbCollectionItemModel[]; total: number } }>;
requestItems(uniques: string[]): Promise<{ data: UmbCollectionItemModel[] }>;
}
核心概念
| 概念 | 描述 |
|---|---|
dataSourceType | Picker Data Source 必须使用 UMB_PICKER_DATA_SOURCE_TYPE |
treePickableFilter | 用于确定哪些树形条目可以被选中的函数 |
searchPickableFilter | 用于确定哪些搜索结果可以被选中的函数 |
requestItems | 根据条目的唯一 ID 返回条目(用于显示已选值) |
entityType | 标识实体类型(用于筛选和路由) |
最佳实践
- 实现搜索 - 用户期望能够搜索包含大量条目的选择器
- 使用合适的图标 - 帮助用户直观地区分条目类型
- 筛选可选条目 - 并非所有树形条目都应可选(例如文件夹)
- 处理配置 - 在适用时支持起始节点和类型筛选器
- 返回一致的数据 - 确保
requestItems返回的数据格式与树形或集合一致
就是这样!请务必获取最新文档,保持示例简洁,并生成完整、可运行的代码。
评论
支持 Markdown