该软件包提供三个 React 组件和一些实用工具,用于处理数据列表:

  • DataViews:使用不同类型的布局(表格、网格、列表)和交互功能(搜索、筛选、排序等)渲染数据集。
  • DataViewsPicker:渲染优化后的数据集,用于选择或挑选项目。
  • DataForm:编辑数据集的项目。

安装

安装模块

npm install @wordpress/dataviews --save

设置

此软件包需要来自此软件包和多个依赖软件包的 CSS。

在 WordPress 内

为确保正确的加载顺序,请将 wp-components 样式表添加为插件样式表的依赖项。有关如何指定依赖项的信息,请参阅 wp_enqueue_style 文档。

在 WordPress 外

在您的应用程序中安装并加载这些样式表:

npm install @wordpress/dataviews @wordpress/theme @wordpress/components
import '@wordpress/theme/design-tokens.css';
import '@wordpress/components/build-style/style.css';
import '@wordpress/dataviews/build-style/style.css';

样式表的 RTL 版本可在相同路径下找到,但文件名后附加了 -rtl(style-rtl.css)。设计令牌样式表是通用的,没有单独的 RTL 版本。

DataViews

在 WordPress Gutenberg 的 Storybook 中有一个 DataViews 组件的示例实现。

用法

DataViews 组件接收数据和一些其他配置来渲染数据集。每当用户以某种方式与数据集交互时(例如排序、筛选、更改布局等),它将调用 onChangeView 回调函数:

DataViews 流程

如果您正在尝试在 WordPress 插件或主题中使用 DataViews 组件,并且您使用 `@wordpress/scripts` 包构建脚本,则需要从 `@wordpress/dataviews/wp` 导入组件,而不是从 `@wordpress/dataviews` 导入。

示例:

import { DataViews } from '@wordpress/dataviews';

const Example = () => {
    const onChangeView = () => {
        /* 响应更改。 */
    };

    return (
        <DataViews
            data={ data }
            fields={ fields }
            view={ view }
            onChangeView={ onChangeView }
            defaultLayouts={ defaultLayouts }
            actions={ actions }
            paginationInfo={ paginationInfo }
        />
    );
};

属性

data: Object[]

一维对象数组。

示例:

const data = [
    {
        id: 1,
        title: '标题',
        author: '管理员',
        date: '2012-04-23T18:25:43.511Z',
    },
    {
        /* ... */
    },
];

数据可以来自任何地方,从静态 JSON 文件到动态源(如 HTTP 请求)。消费者有责任适当查询数据源,并根据用户对排序、筛选等的选择更新数据集。

每条记录都应具有唯一标识它们的 id。如果没有,消费者应提供 getItemId 属性给 DataViews:一个返回记录唯一标识符的函数。

getItemId: function

一个接收项目并返回其唯一标识符的函数。

这是可选的。该字段将由 DataViews 提供一个默认实现,返回 item[ id ] 的值。

示例:

// 自定义 getItemId 函数。
{
    getItemId={ ( item ) => item.name ?? item.id }
}

getItemLevel: function

一个接收项目并返回其层级级别的函数。这是可选的,但如果 view.showLevels 为 true,则必须传递此属性以便 DataViews 显示数据的层级级别。

示例:

// 示例实现
{
    getItemLevel={ ( item ) => item.level }
}

fields: Object[]

字段描述数据集中每条记录的可见项及其行为方式(如何排序、显示等)。有关每个属性的描述,请参阅“Fields API”。

示例:

const STATUSES = [
    { value: 'draft', label: __( '草稿' ) },
    { value: 'future', label: __( '已计划' ) },
    { value: 'pending', label: __( '待审' ) },
    { value: 'private', label: __( '私有' ) },
    { value: 'publish', label: __( '已发布' ) },
    { value: 'trash', label: __( '回收站' ) },
];
const AUTHORS = [
    { value: 1, label: '管理员' },
    { value: 2, label: '用户' },
];

const fields = [
    {
        id: 'title',
        type: 'text',
        label: '标题',
        enableHiding: false,
    },
    {
        id: 'date',
        type: 'date',
        label: '日期',
    },
    {
        id: 'author',
        type: 'integer',
        label: '作者',
        render: ( { item } ) => {
            return AUTHORS.find( ( { value } ) => value === item.author )?.label ??
            item.author,
        },
        elements: AUTHORS,
        filterBy: {
            operators: [ 'is', 'isNot' ],
        },
        enableSorting: false,
    },
    {
        id: 'status',
        type: 'text',
        label: '状态',
        getValue: ( { item } ) =>
            STATUSES.find( ( { value } ) => value === item.status )?.label ??
            item.status,
        elements: STATUSES,
        filterBy: {
            operators: [ 'isAny' ],
        },
        enableSorting: false,
    },
];

view: Object

视图对象配置数据集对用户的可见性。

示例:

const view = {
    type: 'table',
    search: '',
    filters: [
        { field: 'author', operator: 'is', value: 2 },
        { field: 'status', operator: 'isAny', value: [ 'publish', 'draft' ] },
    ],
    page: 1,
    perPage: 5,
    sort: {
        field: 'date',
        direction: 'desc',
    },
    titleField: 'title',
    fields: [ 'author', 'status' ],
    layout: {},
};

属性:

  • type:视图类型,可以是 table、grid、list、activity、pickerTable、pickerGrid、pickerActivity 之一。参见“布局类型”。
  • search:应用于数据集的文本搜索。
  • filters:应用于数据集的筛选器。每项描述:
    • field:此筛选器绑定的字段。
    • operator:筛选器的类型。参见“运算符类型”。
    • value:用户选择的实际值。
    • isLocked:筛选器是否被锁定(用户无法编辑)。
  • perPage:每页显示的记录数。
  • page:当前可见的页面。
  • startPosition:启用无限滚动时要加载的第一项。替代 page 使用。
  • sort:
    • field:用于对数据集排序的字段。
    • direction:用于排序的方向,可以是 asc 或 desc。
  • titleField:代表记录标题的字段 ID。
  • mediaField:代表记录媒体的字段 ID。
  • descriptionField:代表记录描述的字段 ID。
  • showTitle:是否在 UI 中显示标题。默认为 true。
  • showMedia:是否在 UI 中显示媒体。默认为 true。
  • showDescription:是否在 UI 中显示描述。默认为 true。
  • showLevels:是否显示数据的层级级别。默认为 false。参见相关的 getItemLevel DataView 属性。
  • groupBy:
    • field:用于对数据集分组的字段。
    • direction:用于对组排序的方向,可以是 asc 或 desc。默认为 asc。
    • showLabel:是否在组标题中显示字段标签。默认为 true。
  • infiniteScrollEnabled:是否启用无限滚动。默认为 false。
  • fields:在 UI 中可见的剩余字段 id 列表及其显示的具体顺序。
  • layout:特定于某种布局类型的配置。
布局的属性
Props / LayouttablepickerTablegridpickerGridlistactivity
density✓✓✓✓✓✓
enableMoving✓✓
styles✓✓
badgeFields✓✓
previewSize✓✓
aspectRatio✓✓
mediaFit✓✓

table 和 pickerTable 布局:

  • density:可选值为 comfortable、balanced 或 compact。配置布局的大小和间距。
  • enableMoving:是否显示表格列的移动控件。
  • styles:为 fields 中列出的字段提供额外的 width、maxWidth、minWidth、align 样式,以字段 ID 为键。 align 属性接受 'start'、'center' 或 'end'。两种布局都不会将这些样式应用于主列(即渲染 titleField、mediaField 和 descriptionField 的列)。在 table 布局中,该列是弹性列:表格会将每列调整大小以适应其内容,并将剩余宽度分配给主列,因此设置在它上面的 width 或 maxWidth 不会被浏览器的表格布局所尊重,长标题会被截断。当 table 视图没有主列时,fields 中的最后一列会以相同的方式占用剩余宽度。 pickerTable 布局让浏览器在所有列之间共享宽度,但它也不会将样式应用于主列。
  • aspectRatio(仅 table):预设比例之一 '1/1'、'4/3'、'3/4'、'3/2'、'2/3'、'16/9' 或 '9/16',应用于主列的媒体预览。默认为 '1/1'。

关于列对齐(align 属性),请遵循以下准则:
对于本质上定量的单元格值——数字、小数、货币、百分比——请使用右对齐('end'),以便数字和小数点对齐,从而辅助比较和计算。否则,对于所有其他类型(文本、代码、标签、日期),默认使用左对齐('start')。

grid 和 pickerGrid 布局:

  • badgeFields:一组字段的 id 列表,用于渲染不带标签并样式化为徽章的字段。
  • density:可选值为 comfortable、balanced 或 compact。配置网格中项目之间的间隙。
  • previewSize:一个 number,代表预览的大小。
  • aspectRatio(仅 grid):预设比例之一 '1/1'、'4/3'、'3/4'、'3/2'、'2/3'、'16/9' 或 '9/16',统一应用于每个项目的预览,保持行对齐。默认为 '1/1'。
  • mediaFit:媒体字段如何填充预览框,可以是 'cover'(裁剪以填充)或 'contain'(使整个媒体适应内部,添加黑边以保持其自身的宽高比可见)。无论哪种方式,框都会保持由 aspectRatio 设置的形状,因此行保持对齐,并在 'contain' 下采用中性背景,以便添加黑边的预览仍被视为单个项目。默认为 'cover'。若要让用户自行切换此设置,请将 config={ { mediaFitControl: true } } 传递给 DataViews 或 DataViewsPicker,这会在视图选项中添加一个“原始宽高比”切换开关。

list 布局:

  • density:可选值为 comfortable、balanced 或 compact。配置布局的大小和间距。

activity 布局:

  • density:可选值为 comfortable、balanced 或 compact。配置布局的大小和间距。

onChangeView: function

视图更改时执行的回调函数。它接收新的视图对象作为参数。

视图是数据集可见状态的表示:用于显示它的布局类型(如 table、grid 等)、数据集如何过滤以及它是如何排序或分页的。使用者负责使用视图配置查询数据提供者,并确保用户决策(排序、分页、过滤器等)得到尊重。

以下示例展示了如何使用视图对象通过 entities 抽象查询 WordPress REST API。也可以使用任何其他数据提供者来完成相同的操作。

function MyCustomPageTable() {
    const [ view, setView ] = useState( {
        type: 'table',
        perPage: 5,
        page: 1,
        sort: {
            field: 'date',
            direction: 'desc',
        },
        search: '',
        filters: [
            { field: 'author', operator: 'is', value: 2 },
            {
                field: 'status',
                operator: 'isAny',
                value: [ 'publish', 'draft' ],
            },
        ],
        titleField: 'title',
        fields: [ 'author', 'status' ],
        layout: {},
    } );

    const queryArgs = useMemo( () => {
        const filters = {};
        view.filters.forEach( ( filter ) => {
            if ( filter.field === 'status' && filter.operator === 'isAny' ) {
                filters.status = filter.value;
            }
            if ( filter.field === 'author' && filter.operator === 'is' ) {
                filters.author = filter.value;
            }
        } );
        return {
            per_page: view.perPage,
            page: view.page,
            _embed: 'author',
            order: view.sort?.direction,
            orderby: view.sort?.field,
            search: view.search,
            ...filters,
        };
    }, [ view ] );

    const { records } = useEntityRecords( 'postType', 'page', queryArgs );

    return (
        <DataViews
            data={ records }
            view={ view }
            onChangeView={ setView }
            // ...
        />
    );
}

actions: Object[]

可以对数据集执行的操作列表。有关更多详细信息,请参阅“Actions API”。

示例:

const actions = [
    {
        id: 'view',
        label: 'View',
        isPrimary: true,
        icon: <Icon icon={ view } />,
        isEligible: ( item ) => item.status === 'published',
        callback: ( items ) => {
            console.log( 'Viewing item:', items[ 0 ] );
        },
    },
    {
        id: 'edit',
        label: 'Edit',
        icon: <Icon icon={ edit } />,
        supportsBulk: true,
        callback: ( items ) => {
            console.log( 'Editing items:', items );
        },
    },
    {
        id: 'delete',
        label: 'Delete',
        supportsBulk: true,
        RenderModal: ( { items, closeModal, onActionPerformed } ) => (
            <div>
                <p>Are you sure you want to delete { items.length } item(s)?</p>
                <Button
                    variant="primary"
                    onClick={ () => {
                        console.log( 'Deleting items:', items );
                        onActionPerformed();
                        closeModal();
                    } }
                >
                    Confirm Delete
                </Button>
            </div>
        ),
    },
];

paginationInfo: Object

  • totalItems:数据集中项目的总数。
  • totalPages:总页数,考虑到数据集中的总项目数和用户提供的每页项目数。

search: boolean

是否启用搜索输入。默认为 true。

searchLabel: string

在搜索输入中显示的文本。默认为“Search”。

isLoading: boolean

数据是否正在加载。默认为 false。

defaultLayouts: Object

此属性限制可用的布局并提供有关活动视图类型的布局信息。如果为空,则启用所有布局类型(参见“布局类型”),并带有空的布局数据。

例如,这是您如何仅启用表和网格布局类型并设置这些布局是否默认显示媒体的方法:

const defaultLayouts = {
    table: {
        showMedia: false,
    },
    grid: {
        showMedia: true,
    },
};

defaultLayouts 属性应该是一个包含名为 table、grid、list、activity、pickerTable、pickerGrid 和 pickerActivity 属性的对象。每次用户切换到相应的布局时,这些属性都会应用到视图对象上。

selection: string[]

所选项目的 ID 列表。

如果提供了 selection 和 onChangeSelection,则 DataViews 组件的行为类似于受控组件。否则,它表现为非受控组件。

注意:DataViews 仍然需要至少一个批量操作才能使项目可被选中。

onChangeSelection: function

回调函数,用于通知用户已选择一个或多个项目。它接收所选项目的 ID 列表作为参数。

如果提供了 selection 和 onChangeSelection,则 DataViews 组件的行为类似于受控组件。否则,其行为类似于非受控组件。

注意:DataViews 仍然需要至少一个批量操作才能使项目可选。

isItemClickable: function

一个确定媒体字段或主字段是否可点击的函数。它接收一个项目作为参数,并返回一个布尔值,指示该项目是否可以被点击。

请注意,布局仍可能决定不渲染可点击的主字段和媒体字段。例如,list 布局具有不同的交互模型,并且未启用此功能。

onClickItem: function

当点击某个项目时调用的函数。它接收该项目作为参数。

renderItemLink: React.ComponentType

用于渲染可点击项目的渲染函数。

它可以渲染常规链接,但也允许与路由库(如 TanStack Router 或 React Router)集成。

该组件接收以下 props:

  • item:被点击的数据项
  • 其他标准 HTML 锚点 props(className、style 等)
// 然后在 DataViews 中使用
<DataViews
    // ...其他 props
    renderItemLink={ ( { item, ...props } ) => (
        <Link to={ `/sites/${ item.slug }` } preload="intent" { ...props } />
    ) }
/>

header: React component

要渲染在视图配置按钮旁边的 React 组件。

config: { perPageSizes: number[], mediaFitControl?: boolean }

可选。传递一个包含 perPageSizes 列表的对象,以控制每页可用的项目数量(默认为 [10, 20, 50, 100])。perPageSizes 最少需要包含 2 个项目,最多 6 个,否则 UI 组件将不会显示。

将 mediaFitControl 设置为 true 可在网格布局的视图选项中添加“原始宽高比”切换开关,让用户在裁剪(cover)和调整大小以适应(contain)之间切换项目预览。请参阅 mediaFit 布局属性。默认情况下它是关闭的,因为裁剪为统一形状更适合预览已经一致的数据集。当视图不渲染任何媒体字段时,该控件也会被隐藏。

empty: React node

当 data prop 为空时显示的元素。默认为 <p>No results</p>。

onReset: ( () => void ) | false

将视图重置为其默认状态的回调函数,或者使用 false 表示视图未被修改。

  • 类型:function 或 false
  • 可选

此 prop 控制视图配置下拉菜单中的“重置视图”按钮:

  • 当值为 undefined(未提供)时:不显示重置功能。在视图持久化不受支持时使用。
  • 当值为 false 时:显示“重置视图”按钮但处于禁用状态。在视图持久化受支持但当前视图与默认值匹配(未修改)时使用。
  • 当值为函数时:显示“重置视图”按钮并启用。视图选项按钮上会出现蓝色圆点指示器,以表明视图已被修改。当用户点击重置按钮时会调用该函数。

示例:

const { view, setView, isModified, resetToDefault } = useView( 'my-view-key' );

<DataViews
    data={ data }
    view={ view }
    onChangeView={ setView }
    onReset={ isModified ? resetToDefault : false }
    // ...其他 props
/>

Styling

以下是可用于调整组件外观的 CSS Custom Properties:

--wp-dataviews-color-background:设置背景颜色。

Composition modes

DataViews 组件支持两种组合模式:

  • Controlled:这是默认的使用模式。DataViews 开箱即用地呈现完整的布局——包括搜索、过滤器、视图切换器、布局网格或表格、操作和分页。这是最简单的入门方式,所需的设置最少。
  • Free composition:此模式让开发人员完全掌控布局。您可以使用内部组件构建自己的 UI——将它们精确放置在界面中需要的地方。这对于更高级或自定义的布局非常有用,同时仍然依赖于相同的共享上下文来处理用户交互。

组件会根据 children prop 自动检测模式。如果没有传递 children,DataViews 将渲染其内部布局(受控模式)。如果提供了 children,组件将切换到自由组合模式,完全跳过默认布局。

在这两种模式下,用户交互都会更新相同的 view 对象并共享相同的行为。自由组合组件依赖于上下文状态,不需要额外的 props 即可工作,因此无需额外的样板代码即可安全使用。

Free composition

当向 DataViews 组件传递 children prop 时,它进入自由组合模式。在此模式下,DataViews 不再渲染其内置布局——而是作为一个包装器,通过上下文提供对内部状态和共享行为的访问。

这允许您使用 DataViews 暴露的子组件从头构建自己的布局。每个子组件都会自动连接到共享上下文,因此您无需手动连接 props。您可以随意排列这些组件,并将它们与您自己的自定义元素结合使用。

这种模式在保持数据逻辑集中的同时实现了完全的布局灵活性。

以下组件可直接位于 DataViews 之下:

  • DataViews.Search
  • DataViews.FiltersToggle
  • DataViews.FiltersToggled
  • DataViews.Filters
  • DataViews.Layout
  • DataViews.LayoutSwitcher
  • DataViews.Pagination
  • DataViews.BulkActionToolbar
  • DataViews.ViewConfig

example

import DataViews from '@wordpress/dataviews';
import { __ } from '@wordpress/i18n';

const CustomLayout = () => {
    // Declare data, fields, etc.

    return (
        <DataViews
            data={ data }
            fields={ fields }
            view={ view }
            onChangeView={ onChangeView }
            paginationInfo={ paginationInfo }
            defaultLayouts={ { table: {} } }
        >
            <h1>{ __( 'Free composition' ) }</h1>
            <DataViews.Search />
            <DataViews.FiltersToggle />
            <DataViews.FiltersToggled />
            <DataViews.Layout />
            <DataViews.Pagination />
        </DataViews>
    );
};

您可以仅渲染所需的部分,自由重新排列它们,或将它们与自定义组件结合使用。

Accessibility considerations

所有 DataViews 子组件在设计时都考虑了无障碍性——包括键盘交互、焦点管理和语义角色。Search、Pagination、FiltersToggle 和 FiltersToggled 等组件已经在内部处理了这些责任,可以安全地用于自定义布局中。

在使用自由组合时,开发人员负责布局的外部结构。

开发人员无需担心各个功能的内部无障碍逻辑。核心行为——如搜索语义、过滤器切换或分页焦点——已经被封装。

FiltersToggle 控制过滤器面板的可见性,而 Filters 在其内部渲染实际的过滤器。它们协同工作,应始终成对使用。虽然它们的内部行为默认是无障碍的,但它们在自定义布局中的位置和分组方式可能会影响整体体验——特别是对于辅助技术。建议格外小心。

DataViewsPicker

在 WordPress Gutenberg’s Storybook 中有一个 DataviewsPicker 组件的示例实现。

Usage

DataViewsPicker 组件与普通 DataViews 组件非常相似,但针对项目的选择或挑选进行了优化。

与普通 DataViews 组件相比,该组件在以下方面表现不同:

  • 视图中的项目使用 listbox 和 option aria 角色进行渲染。
  • 不需要按住 ctrl 或 cmd 键即可多选项目。可以单击整个项目来选择或取消选择它。
  • 单个项目不显示任何操作。所有操作都以文本按钮的形式出现在页脚中。
  • 当组件分页时,选择状态会在多个页面之间保持。

实现上也有一些差异:

  • 仅支持 DataViewsPicker 的 pickerGrid、pickerTable 和 pickerActivity 布局类型。这些布局分别类似于常规的 grid、table 和 activity 布局。
  • 选择器组件作为“受控”组件使用,因此应提供 selection 和 onChangeSelection 作为 props。这样实现者可以访问跨页面的所有已选中项的完整范围。
  • 可以向 DataViewsPicker 组件提供可选的 itemListLabel prop。这将作为 aria-label 添加到 listbox 元素中,如果 DataViewsPicker UI 没有关联的标题元素,则应提供此属性。
  • DataViewsPicker 不支持 isItemClickable、renderItemLink 和 onClickItem prop。
  • 要实现多选选择器,请确保所有操作都声明为 supportsBulk: true。对于单选,请使用 supportsBulk: false。当同时提供批量和非批量操作时,组件将回退到单选模式。
  • 仅支持 callback 样式的操作。RenderModal 不受支持。
  • 操作的 isEligible 回调会在没有符合条件的选中项时禁用其页脚按钮,并且该回调仅接收符合条件的项。
  • 操作的 isPrimary 选项用于渲染 Button 的 primary 变体,可用作主要的操作号召(call to action)。

示例:

const Example = () => {
    // 使用 DataViewsPicker 时,应管理 `selection` 以使组件成为“受控”组件。
    const [ selection, setSelection ] = useState( [] );

    // 两个操作都具有 `supportsBulk: true`,因此 `DataViewsPicker` 将允许多选。
    const actions = [
        {
            id: 'confirm',
            label: 'Confirm',
            isPrimary: true,
            supportsBulk: true,
            callback() {
                window.alert( selection.join( ', ' ) );
            },
        },
        {
            id: 'cancel',
            label: 'Cancel',
            supportsBulk: true,
            callback() {
                setSelection( [] );
            },
        },
    ];

    return (
        <DataViewsPicker
            actions={ actions }
            data={ data }
            fields={ fields }
            view={ view }
            onChangeView={ onChangeView }
            defaultLayouts={ defaultLayouts }
            paginationInfo={ paginationInfo }
            selection={ selection }
            onChangeSelection={ setSelection }
        />
    );
};

属性

DataViewsPicker 组件接受与 DataViews 大多相同的属性,但有以下关键区别:

data: Object[]

与 DataViews 相同。一个由对象组成的一维数组。

fields: Object[]

与 DataViews 相同。字段描述数据集中每条记录的可见项。有关每个属性的描述,请参阅“Fields API”。

view: Object

与 DataViews 相同。视图对象配置数据集对用户的可见方式。请注意,仅支持 pickerGrid、pickerTable 和 pickerActivity 布局类型。

onChangeView: function

与 DataViews 相同。视图更改时执行的回调。

actions: Object[]

可以对数据集执行的操作列表。更多详细信息请参阅“Actions API”。

与 DataViews 的重要区别:

  • 仅支持 callback 样式的操作。RenderModal 不受支持。
  • 操作的 isEligible 回调会在没有符合条件的选中项时禁用其页脚按钮;该回调仅接收符合条件的项。
  • isPrimary 选项用于渲染 Button 的 primary 变体。
  • 要实现多选,请确保所有操作都具有 supportsBulk: true。对于单选,请使用 supportsBulk: false。

paginationInfo: Object

与 DataViews 相同。包含 totalItems 和 totalPages 属性。

search: boolean

与 DataViews 相同。是否启用搜索输入框。默认为 true。

searchLabel: string

与 DataViews 相同。在搜索输入框中显示的文本。默认为“Search”。

isLoading: boolean

与 DataViews 相同。数据是否正在加载。默认为 false。

defaultLayouts: Record< string, view >

限制可用的布局。仅支持 DataViewsPicker 的 pickerGrid、pickerTable 和 pickerActivity。

示例:

const defaultLayouts = {
    pickerGrid: {
        showTitle: false,
    },
    pickerTable: {},
};

selection: string[]

DataViewsPicker 的必填项。已选中项 ID 的列表。

与 DataViews 不同,选择器组件必须作为受控组件使用,因此需要此 prop 以及 onChangeSelection。

onChangeSelection: function

DataViewsPicker 的必填项。指示用户选择一个或多个项的回调。它接收选中项 ID 列表作为参数。

getItemId: function

与 DataViews 相同。接收一个项并返回其唯一标识符的函数。可选,默认返回 item.id。

itemListLabel: string

可选。列表的可访问标签。这将作为 aria-label 添加到 listbox 元素中,如果 DataViewsPicker UI 没有关联的标题元素,则应提供此属性。

示例:

{
    itemListLabel: 'Select a page';
}

config: { perPageSizes: number[], mediaFitControl?: boolean }

与 DataViews 相同。可选。传递一个包含 perPageSizes 列表的对象以控制每页可用的项目数量,并传递 mediaFitControl 以在网格布局的视图选项中提供“原始纵横比”切换开关。

empty: React node

与 DataViews 相同。当 data prop 为空时显示的元素。

children: React node

可选。自定义 UI,用于替换默认的选取器布局。提供后,您可以免费使用与 DataViews 相同的子组件进行自由组合,以及选取器自己的 DataViewsPicker.Footer、DataViewsPicker.BulkActionToolbar、DataViewsPicker.Actions、DataViewsPicker.PageSelect 和 DataViewsPicker.PageNavigation,即单独使用的页面选择和上一个/下一个按钮。DataViewsPicker.Footer 和 DataViewsPicker.Pagination 会将其子元素渲染在其默认内容的位置,因此选取器可以根据其容纳的空间组合页脚部分:

<DataViewsPicker.Footer>
    <DataViewsPicker.Pagination>
        <DataViewsPicker.PageSelect />
    </DataViewsPicker.Pagination>
    <DataViewsPicker.Actions />
</DataViewsPicker.Footer>

放置组合页脚是消费者的业务,因此这些部分也接受 className,就像 DataViews.Layout 一样,并且页脚可以从消费者自己的样式表中进行布局,而无需用额外元素包裹其部分。

不支持的属性:

以下 DataViews 属性 不被 DataViewsPicker 支持:

  • isItemClickable
  • renderItemLink
  • onClickItem
  • getItemLevel
  • header

DataForm

在 WordPress Gutenberg 的 Storybook 中,有一个 DataForm 组件的示例实现。

用法

const Example = () => {
    // 声明数据、字段等。

    return (
        <DataForm
            data={ data }
            fields={ fields }
            form={ form }
            onChange={ onChange }
        />
    );
};

属性

data: Object

要编辑的单个项。

它可以被视为来自 DataViews 的 data 属性的单个记录——尽管它不一定需要如此。如果您的应用支持批量编辑,它可以完全分离或混合多个记录。

fields: Object[]

字段描述数据的哪些部分是可见的以及它们的行为方式(如何编辑、验证等)。有关每个属性的描述,请参阅“Fields API”。

示例:

const fields = [
    {
        id: 'title',
        type: 'text',
        label: '标题',
    },
    {
        id: 'date',
        type: 'datetime',
        label: '日期',
    },
    {
        id: 'author',
        type: 'text',
        label: '作者',
        elements: [
            { value: 1, label: '管理员' },
            { value: 2, label: '用户' },
        ],
    },
];

form: Object

  • layout: 一个对象,描述用于渲染 fields 中顶级字段的布局。参见“Form Field API”中的 layout 属性。
  • fields: 应渲染的字段 ID 列表。字段 ID 也可以定义为对象,允许你在显示组合字段时定义 layout、labelPosition 或 children。有关每个属性的描述,请参见“Form Field API”。

示例:

const form = {
    layout: {
        type: 'panel',
        labelPosition: 'side',
    },
    fields: [
        'title',
        'data',
        {
            id: 'status',
            label: '状态 & 可见性',
            children: [ 'status', 'password' ],
        },
        {
            id: 'featured_media',
            layout: 'regular',
        },
    ],
};

onChange: function

接收包含用户所做编辑的对象回调函数。

示例:

const data = {
    id: 1,
    title: '标题',
    author: '管理员',
    date: '2012-04-23T18:25:43.511Z',
};

const onChange = ( edits ) => {
    /*
     * edits 将包含用户的编辑内容。
     * 例如,如果用户编辑了标题,
     * edits 将是:
     *
     * {
     *   title: '新标题'
     * }
     *
     */
};

return (
    <DataForm
        data={ data }
        fields={ fields }
        form={ form }
        onChange={ onChange }
    />
);

validity

确定每个字段验证状态的对象。有一个 useFormValidity 钩子可用于创建 validity 对象——见下方的实用工具。本节记录 validity 对象,以防你想通过其他方式创建它。

validity 对象的顶级属性是字段 ID。字段声明其对每种支持验证规则的验证状态:required、elements、pattern、minLength、maxLength、min、max、custom。如果某条规则有效,则不应出现在对象中;如果字段对所有规则都有效,则也不应出现在对象中。

在使用组合字段时,字段的有效性还可以包含 children 属性(Record<string, FieldValidity>)以表示嵌套字段的有效性。

例如:

{
    "title": {
        "required": {
            "type": "invalid"
        }
    },
    "author": {
        "elements": {
            "type": "invalid",
            "message": "值必须是元素之一。"
        }
    },
    "slug": {
        "pattern": {
            "type": "invalid",
            "message": "必须匹配所需模式。"
        }
    },
    "description": {
        "minLength": {
            "type": "invalid",
            "message": "至少需要 10 个字符。"
        },
        "maxLength": {
            "type": "invalid",
            "message": "最多 200 个字符。"
        }
    },
    "price": {
        "min": {
            "type": "invalid",
            "message": "至少为 0。"
        },
        "max": {
            "type": "invalid",
            "message": "最多为 9999。"
        }
    },
    "publisher": {
        "custom": {
            "type": "validating",
            "message": "正在验证..."
        }
    },
    "isbn": {
        "custom": {
            "type": "valid",
            "message": "有效。"
        }
    }
}

每条规则都可以有 type 和 message。

message 是在 UI 控件中显示的文本。required 规则的 message 是可选的,如果未提供,将使用浏览器内置消息。

type 可以是:

  • validating:当值正在被验证时(例如,自定义异步规则)
  • invalid:当值根据规则无效时
  • valid:当值从无效变为有效时(例如,自定义异步规则)

注意 valid 状态。这对于在字段从无效变为有效时显示“有效。”消息很有用。useFormValidity 钩子仅对自定义异步验证实现了此功能。

Utilities

filterSortAndPaginate

实用工具,用于在客户端将视图配置(筛选器、搜索、排序和分页)应用于数据集。

参数:

  • data:数据集,如 DataViews 的“data”属性中所描述。
  • view:视图配置,如 DataViews 的“view”属性中所描述。
  • fields:字段配置,如 DataViews 的“fields”属性中所描述。

返回包含以下内容的对象:

  • data:应用了视图配置后的新数据集。
  • paginationInfo:包含以下属性的对象:
    • totalItems:当前视图配置的项总数。
    • totalPages:当前视图配置的总页数。

useFormValidity

用于确定表单验证状态的钩子。

参数:

  • item:正在编辑的项目。
  • fields:字段配置,如 DataViews 的“fields”属性中所描述。
  • form:表单配置,如 DataViews 的“form”属性中所描述。

返回包含以下内容的对象:

  • isValid:指示表单是否有效的布尔值。
  • validity:包含错误的对象。每个属性是一个字段 ID,包含每种错误类型的描述。更多信息请参见 validity 属性。例如:
{
    fieldId: {
        required: {
            type: 'invalid',
            message: '必填。' // 可选
        },
        elements: {
            type: 'invalid',
            message: '值必须是元素之一。' // 可选
        },
        pattern: {
            type: 'invalid',
            message: '必须匹配所需模式。'
        },
        minLength: {
            type: 'invalid',
            message: '至少需要 10 个字符。'
        },
        maxLength: {
            type: 'invalid',
            message: '最多 200 个字符。'
        },
        min: {
            type: 'invalid',
            message: '至少为 0。'
        },
        max: {
            type: 'invalid',
            message: '最多为 9999。'
        },
        custom: {
            type: 'validating',
            message: '正在验证...'
        }
    }
}

Actions API

id

操作的唯一标识符。

  • 类型:string
  • 必需
  • 示例:move-to-trash

label

面向用户的操作描述。

  • 类型:string | function
  • 必需
  • 示例:
{
    label: '移至回收站'
}

或者

{
    label: ( items ) => ( items.length > 1 ? '删除项目' : '删除项目' );
}

isPrimary

操作是否应以内联方式(主要)显示,还是仅在“更多操作”菜单中显示(次要)。

  • 类型:boolean
  • 可选

icon

主要操作显示的图标。

  • 类型:SVG 元素
  • 主要操作必需,次要操作可选。

isEligible

确定操作是否可以对给定记录执行的函数。

  • 类型:function
  • 可选。如果不存在,则认为该操作适用于所有项目。
  • 示例:
{
    isEligible: ( item ) => item.status === 'published';
}

supportsBulk

操作是否可以同时处理多个项目。

  • 类型:boolean
  • 可选
  • 默认值:false

disabled

操作是否被禁用。

  • 类型:boolean
  • 可选
  • 默认值:false

context

此操作可见的位置。

  • 类型:string
  • 可选
  • 可选值:list、single

callback

执行所需操作的函数。

  • 类型:function
  • 必须提供 callback 或 RenderModal。如果提供了 RenderModal,则将忽略 callback
  • 示例:
{
    callback: ( items, { registry, onActionPerformed } ) => {
        // 执行操作。
        onActionPerformed?.( items );
    };
}

RenderModal

在模态框中渲染操作 UI 的组件。

  • 类型:ReactElement
  • 必须提供 callback 或 RenderModal。如果提供了 RenderModal,则将忽略 callback。
  • 示例:
{
    RenderModal: ( { items, closeModal, onActionPerformed } ) => {
        const onSubmit = ( event ) => {
            event.preventDefault();
            // 执行操作。
            closeModal?.();
            onActionPerformed?.( items );
        };
        return (
            <form onSubmit={ onSubmit }>
                <p>模态框 UI</p>
                <Stack direction="row">
                    <Button variant="tertiary" onClick={ closeModal }>
                        取消
                    </Button>
                    <Button variant="primary" type="submit">
                        提交
                    </Button>
                </Stack>
            </form>
        );
    };
}

hideModalHeader

在使用 RenderModal 时,控制模态框标题的可见性。

  • 类型:boolean
  • 可选
  • 当设置为 false 且使用 RenderModal 时,将使用操作的标签作为模态框标题

modalHeader

要在模态框中显示的标题文本。

  • 类型:string | (items: Item[]) => string
  • 可选
  • 如果提供函数,它将接收选定的项目作为参数,并应返回标题文本

modalSize

在使用 RenderModal 显示操作内容时,指定模态框窗口的大小。

  • 类型:string
  • 可选
  • 默认值:'medium'
  • 可选值:'small', 'medium', 'large', 'fill'

示例:

{
    modalSize: 'large';
}

modalFocusOnMount

指定模态框在挂载时的焦点属性。

  • 类型:boolean | string
  • 可选
  • 默认值:true
  • 可选值:true | false | 'firstElement' | 'firstContentElement'

示例:

{
    modalFocusOnMount: 'firstContentElement';
}

Fields API

id

字段的唯一标识符。

  • 类型:string。
  • 必填。

示例:

{
    id: 'title',
}

type

字段类型。可选值包括 text, integer, number, datetime, date, time, media, boolean, email, password, telephone, color, url, array。

  • 类型:string。
  • 可选。
  • 通过声明类型,该字段将获得所有必要函数(排序、渲染、编辑等)的默认实现。

示例:

{
    id: 'title',
    type: 'text',
}

label

字段的名称。这将在整个 UI 中使用。

  • 类型:string。
  • 可选。
  • 默认值为 id 的值。

示例:

{
    id: 'title',
    type: 'text',
    label: 'Title',
}

header

某些布局(表格、网格)用于显示字段名称的 React 元素——可用于添加图标等。

  • 类型:string | React 元素。
  • 可选。
  • 默认值为 label 的值。

示例:

{
    id: 'title',
    type: 'text',
    header: (
        <Stack direction="row" gap="xs" justify="start">
            <Icon icon={ icon } />
            <span>Title</span>
        </Stack>
    ),
}

description

描述字段用途或使用的字符串。用于在编辑模式下提供上下文等。

  • 类型:string。
  • 可选。

placeholder

用作占位符的字符串,例如在编辑模式下。

  • 类型:string。
  • 可选。

getValue 和 setValue

这些函数控制如何从您的数据结构中读取字段值以及如何写入字段值。

这两个函数都是可选的,如果未提供,则会根据字段的 id 自动生成。id 被视为点表示法路径(例如,"user.profile.name" 访问 item.user.profile.name)。

getValue

从项目中提取字段值的函数。该值用于排序、过滤和显示字段。

  • 类型:function。
  • 可选。
  • 参数:
    • item:要处理的数据项。
  • 返回字段的值。

setValue

创建具有更新字段值的局部项目对象的函数。DataForm 使用此函数进行编辑操作,并确定传递给 onChange 回调的数据结构。

  • 类型:function。
  • 可选。
  • 参数:
    • item:当前正在编辑的项目。
    • value:要为字段设置的新值。
  • 返回带有待应用更改的局部项目对象。

简单字段访问

对于基本字段访问,您只需指定字段 id。getValue 和 setValue 会自动生成:

// 数据结构
const item = {
    title: 'Hello World',
    author: 'John Doe'
};

// 字段定义
{
    id: 'title',
    type: 'text',
    label: 'Title'
    // getValue: 自动变为 ( { item } ) => item.title
    // setValue: 自动变为 ( { value } ) => ( { title: value } )
}

嵌套数据访问

在字段 id 中使用点表示法来访问嵌套属性:

// 数据结构
const item = {
    user: {
        profile: {
            name: 'John Doe',
            email: 'john@example.com'
        }
    }
};

// 字段定义 - 使用点表示法(自动)
{
    id: 'user.profile.name',
    type: 'text',
    label: 'User Name'
    // getValue: 自动变为 ( { item } ) => item.user.profile.name
    // setValue: 自动变为 ( { value } ) => ( { user: { profile: { name: value } } } )
}

// 替代方案 - 使用简单 ID 和自定义函数
{
    id: 'userName',
    type: 'text',
    label: 'User Name',
    getValue: ( { item } ) => item.user.profile.name,
    setValue: ( { value } ) => ( {
        user: {
            profile: { name: value }
        }
    } )
}

自定义数据转换

当需要在存储格式和显示格式之间转换数据时,提供自定义的 getValue 和 setValue 函数:

// 数据结构
const item = {
    user: {
        preferences: {
            notifications: true
        }
    }
};

// 字段定义 - 将布尔值转换为字符串选项
{
    id: 'notifications',
    type: 'boolean',
    label: 'Notifications',
    Edit: 'radio',
    elements: [
        { label: 'Enabled', value: 'enabled' },
        { label: 'Disabled', value: 'disabled' }
    ],
    getValue: ( { item } ) =>
        item.user.preferences.notifications === true ? 'enabled' : 'disabled',
    setValue: ( { value } ) => ( {
        user: {
            preferences: { notifications: value === 'enabled' }
        }
    } )
}

getValueFormatted

根据字段的 format 配置计算格式化后的字段值,以便显示。格式化后的值用于在不同上下文中保持一致的值呈现。例如,由字段类型提供的默认 render 实现以及显示值的过滤器组件。

  • 类型:function。
  • 可选。
  • 每个字段 type 都提供一个默认实现,以适当的方式格式化值(例如,考虑 weekStartsOn 用于日期,千位分隔符用于数字等)。
  • 参数:
    • item:包含值的數據項。
    • field:规范化后的字段配置。
  • 返回用于显示的格式化值(通常为字符串)。

一些自定义 getValueFormatted 函数的示例:

// 将数字格式化为货币
{
    id: 'price',
    type: 'number',
    label: 'Price',
    getValueFormatted: ( { item, field } ) => {
        const value = field.getValue( { item } );
        if ( value === null || value === undefined ) {
            return '';
        }

        return `$${ value.toFixed( field.format.decimals ) }`;
    }
}
// 使用自定义逻辑格式化日期
{
    id: 'publishDate',
    type: 'date',
    label: 'Published',
    getValueFormatted: ( { item, field } ) => {
        const value = field.getValue( { item } );
        if ( ! value ) {
            return 'Not published';
        }

        const date = new Date( value );
        const now = new Date();
        const diffDays = Math.floor( ( now - date ) / ( 1000 * 60 * 60 * 24 ) );
        if ( diffDays === 0 ) {
            return 'Today';
        }
        if ( diffDays === 1 ) {
            return 'Yesterday';
        }
        return `${ diffDays } days ago`;
    }
}

render

渲染字段的 React 组件。

  • 类型:React 组件。
  • 可选。
  • 字段 type 提供了一个默认的渲染方式,该方式使用 getValueFormatted 来显示值,并使用 elements 进行标签查找(如果提供了的话)。
  • 属性
    • item 要处理的数据项。
    • field 当前字段的配置。用于访问 getValue、elements 等属性。
    • config 包含字段配置选项的对象。它是可选的。目前唯一可用的对象属性是 sizes:在设置为媒体字段的字段中,布局可以将为其保留的预期尺寸传递下来,以便字段能够相应地做出反应。
  • 返回一个代表字段值的 React 元素。

自定义渲染函数的示例:

{
    id: 'title',
    type: 'text',
    label: 'Title',
    render: ( { item, field, config } ) => {
        /* 要显示的 React 元素。 */
    };
}

Edit

用于渲染编辑字段控件的 React 组件。

  • 类型:string | object | React 组件。
  • 可选。
  • 字段 type 提供了默认实现。

提供了 type 的字段将拥有一个默认的 Edit 控件:

{
    id: 'categories',
    type: 'text',
    label: 'Categories',
}

字段作者可以通过提供一个字符串来覆盖默认的 Edit 控件,该字符串映射到捆绑的 UI 控件之一:array、checkbox、color、date、datetime、email、integer、number、password、radio、select、telephone、text、textarea、time、toggle、toggleGroup 或 url。

{
    id: 'categories',
    type: 'text',
    label: 'Categories',
    Edit: 'radio',
}

此外,部分捆绑的 Edit 控件可以通过配置对象进行配置:

  • textarea 配置:
{
    id: 'description',
    type: 'text',
    label: 'Description',
    Edit: {
        control: 'textarea',
        rows: 5
    }
}
  • text 配置:
{
    id: 'title',
    type: 'text',
    label: 'Title',
    Edit: {
        control: 'text',
        prefix: ReactComponent,
        suffix: ReactComponent,
    }
}
  • datetime 配置:
{
    id: 'date',
    type: 'datetime',
    label: 'Date',
    Edit: {
        control: 'datetime',
        compact: true
    }
}

最后,字段作者始终可以提供自己的自定义 Edit 控件。它接收以下属性:

  • data:要处理的数据项
  • field:字段定义
  • onChange:带有更新内容的回调函数
  • hideLabelFromVision:布尔值,表示是否应隐藏标签
  • markWhenOptional:布尔值,指示当字段非必需时,是否应将控件标记为“可选”,而不是显示“必填”
  • operator:此字段当前选定的筛选操作符。DataViews 筛选器使用它来确定基于操作符类型应渲染哪个控件
  • validity:表示字段值有效性的对象(参见有效性部分)
  • config:表示组件额外配置的对象:
    • prefix:作为前缀渲染的 React 组件
    • suffix:作为后缀渲染的 React 组件
    • rows:要显示的行数(例如,在文本区域组件中)
    • compact:是否渲染不带日历小部件的紧凑版本(datetime 控件)
{
    id: 'time',
    type: 'datetime',
    label: 'Time of day',
    Edit: ( {
        data,
        field,
        onChange,
        hideLabelFromVision,
        validity,
        config,
    } ) => {
        const value = field.getValue( { item: data } );

        return (
            <CustomTimePicker
                value={ value }
                onChange={ onChange }
                hideLabelFromVision
            />
        );
    };
}

readOnly

布尔值,指示在编辑上下文中不应渲染 Edit 控件,而是以只读方式显示。只读字段使用 render 函数而不是其 Edit 组件来显示其值(例如,在 DataForm 中)。这与禁用字段不同(参见 isDisabled),禁用字段仍然会渲染其 Edit 组件,但在特定情况下被禁用。

  • 类型:boolean。
  • 可选。
  • 默认为 false。

isDisabled

指示字段在编辑上下文(例如 DataForm)中是否应被禁用。与只读字段(参见 readOnly)不同,禁用字段拥有 Edit 组件,但控件在特定情况下被禁用。

  • 类型:boolean 或 function。
  • 可选。
  • 参数
    • item:要处理的数据
    • field:字段定义
  • 返回一个 boolean,指示字段是否应被禁用(true)或不禁用(false)。

这对于根据其他字段的状态禁用字段非常有用。例如,password 字段可以根据 status 字段的值被禁用:

{
 id: 'status',
 type: 'text',
 label: 'Status',
 elements: [
  { value: 'public', label: 'Public' },
  { value: 'private', label: 'Private' },
 ],
},
{
 id: 'password',
 type: 'password',
 label: 'Password',
 isDisabled: ( { item } ) => item.status === 'private',
},

sort

对记录进行排序的函数。

  • 类型:function。
  • 可选。

当字段声明了类型时,它会获得一个默认的排序函数:

{
    id: 'title',
    type: 'text',
    label: 'Title',
}

可以通过提供自定义排序函数来覆盖默认排序。它接受以下参数:

  • a:第一个比较项的字段值(由 getValue 返回)
  • b:第二个比较项的字段值(由 getValue 返回)
  • direction:可以是 asc(升序)或 desc(降序)

它应该返回一个数字,其中:

  • 负值表示 a 应排在 b 之前
  • 正值表示 a 应排在 b 之后
  • 0 表示 a 和 b 被视为相等
{
    id: 'title',
    type: 'text',
    label: 'Title',
    sort: ( a, b, direction ) => {
        return direction === 'asc'
            ? a.localeCompare( b )
            : b.localeCompare( a );
    };
}

isValid

包含字段验证规则的对象。如果未满足某个规则,控件将被标记为无效,并显示一条消息。

  • required:布尔值,指示字段是否为必填项。默认禁用。
  • elements:布尔值,限制选择仅限提供的元素列表。默认启用。array Edit 控件使用它来限制输入值。
  • pattern:字段值必须匹配的 regex 模式字符串。
  • minLength:字段值的最小字符串长度。
  • maxLength:字段值的最大字符串长度。
  • min:字段的最小数值。
  • max:字段的最大数值。
  • custom:一个验证字段值的函数。如果值无效,函数应返回一个解释值为何无效的字符串。否则,函数必须返回 null。

定义了类型的字段自带针对该类型的默认验证。例如,integer 类型确保值为有效的整数:

{
    id: 'itemsSold',
    type: 'integer',
    label: 'Items sold',
}

字段作者可以覆盖验证规则。例如,将字段设置为必填,或提供自定义验证以仅使偶数为有效值:

{
    id: 'itemsSold',
    type: 'integer',
    label: 'Items sold',
    isValid: {
        required: true,
        custom: ( item: Item, field: NormalizedField<Item> ) => {
            if ( field.getValue({ item }) % 2 !== 0 ) {
                return 'Integer must be an even number.';
            }

            return null;
        }
    }
}

定义了自定义 Edit 组件的字段可以通过 field.isValid 对象访问验证规则:

{
    id: 'itemsSold',
    type: 'integer',
    label: 'Items sold',
    Edit: ( { field } ) => {
        return <input required={ !! field.isValid.required } />;
    };
}

isVisible

指示字段是否可见的函数。

  • 类型:function。
  • 可选。
  • 参数
    • item: 待处理的数据
  • 返回一个 boolean,指示字段是否可见(true)或不可见(false)。

通过 isVisible 隐藏的字段不会进行验证:在隐藏期间会跳过其验证规则,并在重新变为可见时再次应用这些规则。

这可用于根据其他字段的状态来隐藏字段。例如,可以根据 homepageDisplay 字段的值来隐藏 staticHomepage 字段:

{
    id: 'homepageDisplay',
    type: 'text',
    label: 'Homepage display',
    elements: [
        { value: 'latest', label: 'Latest post' },
        { value: 'static', label: 'Static page' },
    ],
},
{
    id: 'staticHomepage',
    type: 'text',
    label: 'Static homepage',
    elements: [
        { value: 'welcome', label: 'Welcome to my website' },
        { value: 'about', label: 'About' },
    ],
    isVisible: ( item ) => item.homepageDisplay === 'static',
},

enableSorting

布尔值,指示该字段是否可排序。

  • 类型:boolean。
  • 可选。
  • 默认为 true。

禁用字段排序的示例:

{
    id: 'title',
    type: 'text',
    label: 'Title',
    enableSorting: false,
}

enableHiding

布尔值,指示该字段是否可以隐藏。

  • 类型:boolean。
  • 可选。
  • 默认为 true。

禁用字段隐藏的示例:

{
    id: 'title',
    type: 'text',
    label: 'Title',
    enableHiding: false,
}

enableGlobalSearch

布尔值,指示该字段是否可搜索。

  • 类型:boolean。
  • 可选。
  • 默认为 false。

启用字段全局搜索的示例:

{
    id: 'title',
    type: 'text',
    label: 'Title',
    enableGlobalSearch: true,
}

elements

字段的有效值列表。如果提供此属性,字段的筛选器将使用这些值作为预定义选项供用户选择。

  • 类型:array 对象数组。
  • 可选。
  • 每个对象可以具有以下属性:
    • value: 与字段值进行匹配的值。(必填)
    • label: 向用户显示的名称。(必填)
    • description: 可选,该项的更长描述。

示例:

{
    id: 'selectedProduct',
    type: 'integer',
    label: 'Selected product',
    elements: [
        { value: '1', label: 'Product A' },
        { value: '2', label: 'Product B' },
        { value: '3', label: 'Product C' },
        { value: '4', label: 'Product D' },
    ]
}

getElements

异步函数,仅在需要时获取元素,从而实现懒加载。它返回一个解析为元素数组的 Promise。

注意,此函数在 DataViews/DataForm 组件的生命周期内可能会被调用多次。例如,如果在字段的 render 方法中使用了 elements,它将在页面中显示的每条记录上触发一次。消费者有责任缓存结果,以避免不必要的昂贵操作(如网络请求等)。

{
    id: 'selectedProduct',
    type: 'integer',
    label: 'Selected product',
    getElements: () => {
        return Promise.resolve( [
            { value: '1', label: 'Product A' },
            { value: '2', label: 'Product B' },
            { value: '3', label: 'Product C' },
            { value: '4', label: 'Product D' },
        ] );
    }
}

filterBy

筛选器的配置。设置为 false 以完全排除该字段的筛选功能。

  • 类型:object | boolean。
  • 可选。
  • 如果为 false,则该字段不可用于筛选。
  • 如果为对象,它可以具有以下属性:
    • operators: 该字段支持的操作符列表。参见下方的“operators”。
    • isPrimary: 布尔值,可选。指示筛选器是否为主筛选器。主筛选器始终可见,且不出现在“添加筛选器”组件中,但在列表布局中其行为类似于次级筛选器。

默认情况下,字段通过使用字段的 Edit 函数启用筛选:

{
    id: 'product',
    type: 'text',
    label: 'Product',
}

如果字段提供了 elements,则筛选器将使用这些值作为预定义选项:

{
    id: 'product',
    type: 'text',
    label: 'Title',
    elements: [
        { value: 'a', label: 'Product A' },
        { value: 'b', label: 'Product B' },
        { value: 'c', label: 'Product C' },
        { value: 'd', label: 'Product D' },
    ]
}

通过将 filterBy 设置为 false,字段可以选择退出筛选:

{
    id: 'product',
    type: 'text',
    label: 'Product',
    filterBy: false;
}

字段可以将其筛选器声明为主筛选器,这意味着它将始终可见且用户无法移除:

{
    id: 'title',
    type: 'text',
    label: 'Title',
    filterBy: {
        isPrimary: true;
    }
}

每种字段类型的筛选器都带有默认的操作符,但字段本身可以进行配置。例如,字段可以为筛选器仅启用单选操作符:

{
    id: 'product',
    type: 'text',
    label: 'Product',
    elements: [
        { value: 'a', label: 'Product A' },
        { value: 'b', label: 'Product B' },
        { value: 'c', label: 'Product C' },
        { value: 'd', label: 'Product D' },
    ],
    filterBy: {
        operators: [ `is`, `isNot` ];
    }
}

或者多选操作符:

{
    id: 'product',
    type: 'text',
    label: 'Product',
    elements: [
        { value: 'a', label: 'Product A' },
        { value: 'b', label: 'Product B' },
        { value: 'c', label: 'Product C' },
        { value: 'd', label: 'Product D' },
    ],
    filterBy: {
        operators: [ `isAny`, `isNone` ];
    }
}

下表列出了所有可用的操作符:

操作符描述示例
after结果在给定的日期之后。日期晚于:2024-01-01
afterInc结果在给定的日期之后,包含该日期。日期在或晚于:2024-01-01
before结果在给定的日期之前。日期早于:2024-01-01
beforeInc结果在给定的日期之前,包含该日期。日期在或早于:2024-01-01
between结果在两个值之间。数量介于(含):10 和 180
contains结果包含给定的子字符串。标题包含:Mars
greaterThan结果在数值上大于单个值。年龄大于:65
greaterThanOrEqual结果在数值上大于或等于单个值。年龄大于或等于:65
inThePast结果在当前时间之前的 N 个单位(天、周、月或年)内。过去订单:7 天前
isAll结果包含列表中的所有值。类别包含全部:Book, Review, Science Fiction
isAny结果包含列表中的部分值。作者包含:Admin, Editor
isNone结果不包含列表中的部分值。作者排除:Admin, Editor
is结果等于单个值。作者是:Admin
isNot结果不等于单个值。作者不是:Admin
lessThan结果在数值上小于单个值。年龄小于:18
lessThanOrEqual结果在数值上小于或等于单个值。年龄小于或等于:18
notContains结果不包含给定的子字符串。描述不包含:photo
notOn结果不在给定的日期上(使用正确的日期解析进行日期不等比较)。日期不是:2024-01-01
on结果在给定的日期上(使用正确的日期解析进行日期相等比较)。日期是:2024-01-01
over结果比当前时间早 N 个单位(天、周、月或年)。超过订单:7 天前
startsWith结果以给定的子字符串开头。标题以 Mar 开头

部分运算符为单选:is、isNot、on、notOn、lessThan、greaterThan、lessThanOrEqual、greaterThanOrEqual、before、after、beforeInc、afterInc、contains、notContains 和 startsWith。其他为多选:isAny、isNone、isAll。过滤器不能混用单选和多选运算符;如果有效运算符列表中存在单选运算符,多选运算符将被丢弃,且过滤器不允许选择多个项目。

每种字段类型的有效运算符:

  • array(数组): isAny、isNone、isAll。
  • boolean(布尔值): is、isNot。
  • color(颜色): is、isNot、isAny、isNone。
  • date(日期): on、notOn、before、beforeInc、after、afterInc、inThePast、over、between。
  • datetime(日期时间): on、notOn、before、beforeInc、after、afterInc、inThePast、over。
  • email(电子邮件): is、isNot、contains、notContains、startsWith、isAny、isNone。
  • integer(整数): is、isNot、lessThan、greaterThan、lessThanOrEqual、greaterThanOrEqual、between、isAny、isNone。
  • media(媒体):无。
  • number(数字): is、isNot、lessThan、greaterThan、lessThanOrEqual、greaterThanOrEqual、between、isAny、isNone。
  • password(密码):无。
  • telephone(电话): is、isNot、contains、notContains、startsWith、isAny、isNone。
  • text(文本): is、isNot、contains、notContains、startsWith、isAny、isNone。
  • time(时间): on、notOn、before、beforeInc、after、afterInc、between。
  • url(网址): is、isNot、contains、notContains、startsWith、isAny、isNone。
  • 无类型的字段:任何运算符。

time 与 date 和 datetime 共享排序运算符,这些运算符通用地比较时间值:日期或日期时间按其日历位置进行比较,时间按其在一天中的位置进行比较。比较不敏感于精度,因此针对 '09:00' 的过滤器匹配存储的 '09:00:00'。

inThePast 和 over 是例外,对 time 无效:它们从当前时间向后测量,而一天中的时间无法锚定到这一点。

format

字段的显示格式配置。支持 datetime、date、time、number 和 integer 字段。此配置影响字段在 render 方法、Edit 控件以及过滤器控件中的显示方式。

  • 类型:object。
  • 可选。

对于 datetime 字段:
– 属性:
– datetime:使用 PHP 日期格式的格式字符串(例如,'Jan 1, 2021 2:30 pm' 对应 'M j, Y g:i a')。可选,默认为 WordPress 日期格式设置。
– weekStartsOn:指定日历控件中一周的第一天。值为 0、1、2、3、4、5、6 之一。可选,默认为 WordPress “Week Starts On” 设置,其值为 0(星期日)。

示例:

{
    id: 'createdAt',
    type: 'datetime',
    label: 'Created At',
    format: {
        datetime: 'M j, Y g:i a',
        weekStartsOn: 1,
    },
}

对于 date 字段:
– 属性:
– date:使用 PHP 日期格式的格式字符串(例如,‘March 10, 2023’ 对应 ‘F j, Y’)。可选,默认为 WordPress “Date Format” 设置。
– weekStartsOn:指定日历控件中一周的第一天。值为 0、1、2、3、4、5、6 之一。可选,默认为 WordPress “Week Starts On” 设置,其值为 0(星期日)。

示例:

{
    id: 'publishDate',
    type: 'date',
    label: 'Publish Date',
    format: {
        date: 'F j, Y',
        weekStartsOn: 1,
    },
}

对于 time 字段:

  • 属性:
    • time:使用 PHP 日期格式的格式字符串(例如,'2:30 pm' 对应 'g:i a')。可选,默认为 WordPress “Time Format” 设置。

Edit 控件是否提供秒字段遵循以下格式:当格式字符串渲染秒时(例如 'H:i:s'),则提供;否则不提供。

仅使用时间标记。因为时间没有关联日期,日期和时区标记没有有意义的渲染内容,并将发出该值内部锚定的占位符日期 — 'F j, Y g:i a' 将渲染为 'January 1, 2000 2:30 pm'。如果字段需要日期,请使用 datetime。

示例:

{
    id: 'opensAt',
    type: 'time',
    label: 'Opens At',
    format: {
        time: 'g:i a',
    },
}

time 值是一个没有关联日期的时间点,存储为 HH:mm 或 HH:mm:ss(RFC 3339 partial-time)。值为墙钟时间:接受尾随的 UTC 偏移量但将其忽略而非应用,无论访问者处于哪个时区,值的渲染都相同。如果时间需要表示特定瞬间,请改用 datetime。

对于 number 字段:

  • 属性:
    • separatorThousand:用作千位分隔符的字符(例如,‘1,234’ 中的 ‘,’)。可选,默认为 ‘,’。
    • separatorDecimal:用作小数分隔符的字符(例如,‘1.23’ 中的 ‘.’)。可选,默认为 ‘.’。
    • decimals:要显示的小数位数(0-100)。可选,默认为 2。

示例:

{
    id: 'price',
    type: 'number',
    label: 'Price',
    format: {
        separatorThousand: ',',
        separatorDecimal: '.',
        decimals: 2,
    },
}

对于 integer 字段:

  • 属性:
    • separatorThousand:用作千位分隔符的字符(例如,‘1,234’ 中的 ‘,’)。可选,默认为 ‘,’。

示例:

{
    id: 'quantity',
    type: 'integer',
    label: 'Quantity',
    format: {
        separatorThousand: ',',
    },
}

Form Field API

id

字段的唯一标识符。

  • 类型:string。
  • 必填。

示例:

{
    id: 'field_id';
}

layout

表示用于渲染字段的布局类型。它将是 Regular、Panel、Card、Row 或 Details 之一。此 prop 与 form.layout prop 相同。

Regular

  • type:regular。必填。
  • labelPosition:side、top 或 none 之一。可选。默认为 top。

例如:

{
    id: 'field_id',
    layout: {
        type: 'regular',
        labelPosition: 'side'
    },
}

Panel

  • type:panel。必填。
  • labelPosition:side、top 或 none 之一。可选。默认为 side。
  • editVisibility:always 或 on-hover 之一。可选。默认为 on-hover。
  • showPlaceholderIfEmpty:布尔值。可选。默认为 false。当字段值为 undefined、null 或空字符串时,摘要是否显示字段的 placeholder 而不是其 render 输出。
  • openAs:dropdown 或 modal 之一。可选。默认为 dropdown。
  • summary:摘要字段配置。可选。指定要在面板标题中显示哪些字段。可以是:
    • 一个字符串(单个字段 ID)
    • 字符串数组(多个字段 ID)

当未明确配置摘要字段时,面板会自动根据以下优先级确定要显示的字段:

  1. 如果存在 summary 字段,则使用它们
  2. 回退到与表单字段 id 匹配的字段定义
  3. 如果表单字段 id 不存在,则选择第一个子字段
  4. 如果未找到字段定义,则返回空的摘要字段

例如:

{
    id: 'field_id',
    layout: {
        type: 'panel',
        labelPosition: 'top'
    },
}

Card

  • type:card。必填。
  • isOpened:布尔值。可选。默认为 true。
  • withHeader: boolean。可选。默认为 true。
  • summary: 摘要字段配置。可选。指定要在卡片标题中显示哪些字段。可以是:
    • 字符串(单个字段 ID)
    • 字符串数组(多个字段 ID)
    • 用于按字段控制可见性的对象数组 [{ id: string, visibility: 'always' | 'when-collapsed' }]
  • isCollapsible: boolean。可选。默认为 true。指定卡片是否可以折叠。

卡片在可见时也可以折叠,因此您可以控制摘要字段的出现时机:

  • 'always':在展开和折叠状态下均显示该字段。
  • 'when-collapsed':仅在卡片折叠时显示该字段。这是默认值。

例如:

{
    id: 'field_id',
    layout: {
        type: 'card',
        isOpened: false,
        withHeader: true,
    },
}

Row(行)

  • type: row。必需。
  • alignment: start、center 或 end 之一。可选。默认为 center。
  • styles: 一个将字段 ID 映射到样式对象的对象。每个样式对象支持 flex 属性(任何有效的 CSS flex 值),以控制在行内字段的大小调整方式。可选。

Row 布局将字段水平显示在单行中。它特别适用于分组应并排显示的关联字段。此布局既可作为顶级表单布局使用,也可用于各个字段组。

例如:

{
    id: 'field_id',
    layout: {
        type: 'row',
        alignment: 'start',
        styles: {
            field1: { flex: '1 1 auto' },
            field2: { flex: '0 0 200px' },
        },
    },
}

Details(详情)

  • type: details。必需。
  • summary: 摘要字段配置。可选。指定要在详情摘要中显示的字段。为字符串(单个字段 ID)

Details 布局将字段渲染在可折叠的 HTML 元素 <details> 内部。summary 属性控制披露摘要中显示的文本。

例如:

{
    id: 'field_id',
    layout: {
        type: 'details',
        summary: 'summaryFieldId'
    },
}

label

在显示组合字段时使用的标签,这需要同时使用 children。

  • 类型:string。

示例:

{
    id: 'field_id',
    label: 'Combined Field',
    children: [ 'field1', 'field2' ]
}

description

描述表单字段用途或用法的一段字符串。用于提供额外的上下文信息。

  • 类型:string。
  • 可选。

示例:

{
    id: 'field_id',
    label: 'Status & Visibility',
    description: 'Control the publish status and visibility of the post.',
    children: [ 'status', 'password' ],
}

children

将一组在 children 中定义的字段进行分组。例如,如果您希望在 Panel 下拉菜单中显示多个字段,可以使用 children(参见示例)。

  • 类型:Array< string | FormField >。

示例:

{
    id: 'status',
    layout: {
        type: 'panel',
    },
    label: 'Combined Field',
    children: [ 'field1', 'field2' ],
}

为此包做出贡献

这是一个作为 Gutenberg 项目一部分的独立包。该项目采用 monorepo 组织形式。它由多个自包含的软件包组成,每个包都有特定的用途。此 monorepo 中的软件包发布到 npm,并被 WordPress 以及其他软件项目使用。

要了解有关为此包或整个 Gutenberg 做出贡献的更多信息,请阅读项目的主 贡献者指南。