mcpField
U
umbraco-picker-data-source

umbraco-picker-data-source

github.com/umbraco开发27388 次安装6 周前更新
代码仓库

关于 umbraco-picker-data-source

这是面向 Umbraco 开发者的技能,用于为选择器属性编辑器创建数据源。它帮助定义数据获取、搜索和树形或集合展示,并生成相应清单与数据源类。

主要功能

  1. 01创建树形或集合数据源
  2. 02定义数据获取和搜索
  3. 03配置可选项目筛选
  4. 04生成清单和数据源类

适用场景

  1. 01从外部 API 提供选择项
  2. 02构建带搜索的树形选择器
  3. 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 或现有内容的筛选子集中进行选择的选择器。

文档

实现前,请务必获取最新文档:

参考示例

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

工作流

  1. 获取文档 - 对上述 URL 使用 WebFetch
  2. 提问 - 要选择什么数据?使用树形还是集合?是否需要搜索?有哪些配置选项?
  3. 生成文件 - 根据最新文档创建 manifest 和数据源类
  4. 说明 - 展示创建的内容,以及如何与属性编辑器搭配使用

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

核心概念

概念描述
dataSourceTypePicker Data Source 必须使用 UMB_PICKER_DATA_SOURCE_TYPE
treePickableFilter用于确定哪些树形条目可以被选中的函数
searchPickableFilter用于确定哪些搜索结果可以被选中的函数
requestItems根据条目的唯一 ID 返回条目(用于显示已选值)
entityType标识实体类型(用于筛选和路由)

最佳实践

  1. 实现搜索 - 用户期望能够搜索包含大量条目的选择器
  2. 使用合适的图标 - 帮助用户直观地区分条目类型
  3. 筛选可选条目 - 并非所有树形条目都应可选(例如文件夹)
  4. 处理配置 - 在适用时支持起始节点和类型筛选器
  5. 返回一致的数据 - 确保 requestItems 返回的数据格式与树形或集合一致

就是这样!请务必获取最新文档,保持示例简洁,并生成完整、可运行的代码。

评论

支持 Markdown