Gutenberg 在 selectControl 更改时保存数据以发布元字段

问题描述 投票:0回答:1

我是 React 和 JSX 的新手,一直致力于 WP 侧边栏中的选择菜单下拉字段。 此选择菜单显示当前添加的帖子类别,并且该部分工作正常。

我不明白的地方是如何保存此选择以及如何使用选择控制区域中的所选选项更新后元字段。

我在 functions.php 文件中使用 register_meta 创建了一个后元字段:

<?php
register_meta( 'post', '_myprefix_text_metafield', array(
    'show_in_rest' => true,
    'type' => 'string',
    'single' => true,
    'sanitize_callback' => 'sanitize_text_field',
    'auth_callback' => function ()
    {
        return current_user_can( 'edit_posts' );
    }
) );

然后我有一个包含以下脚本的 index.js 文件:

/**
 * https://developer.wordpress.org/block-editor/reference-guides/packages/packages-plugins/#registerplugin
 * https://developer.wordpress.org/block-editor/reference-guides/components/select-control/#usage-2
 */
(function (wp) {
    const { registerPlugin } = wp.plugins;
    const { SelectControl } = wp.components;
    const { PluginDocumentSettingPanel } = wp.editPost;
    const { useSelect } = wp.data;
    const { useState } = wp.element;

    registerPlugin('spectator-primary-category', {
        render: function () {

            const { categories } = useSelect((select) => {
                const { getEntityRecords } = select('core');

                return {
                    categories: getEntityRecords('taxonomy', 'category'),
                }
            })

            let [selectedCategory, setSelectedCategory] = useState([]);

            let options = [];
            if (categories) {
                options = categories.map(category => ({ label: category.name, value: category.id }));
                options.unshift({ value: 0, label: 'Select a category' });
                console.log(options);
            }

            return (
                <PluginDocumentSettingPanel
                    name="spectator-primary-category-panel"
                    title="Add the primary category"
                    className="spectator-primary-category__panel"
                >
                    <SelectControl
                        value={selectedCategory}
                        options={options}
                        onChange={(tokens) => setSelectedCategory(tokens)}
                    />
                </PluginDocumentSettingPanel>
            )
        },
        icon: 'airplane' // or false if you do not need an icon
    });
})(window.wp);

我已经花了 8 个多小时浏览互联网,但未能实现我所需要的。有好心人能告诉我如何保存这些数据吗?

===更新===

感谢@kofiegan 帮助我理解这是如何工作的,我能够更新元字段并显示结果。这是最终使用的代码:

/**
 * https://developer.wordpress.org/block-editor/reference-guides/packages/packages-plugins/#registerplugin
 * https://developer.wordpress.org/block-editor/reference-guides/components/select-control/#usage-2
 * https://stackoverflow.com/questions/75816358/gutenberg-save-data-to-post-meta-field-when-selectcontrol-is-changed
 */
(function (wp) {
    const { registerPlugin } = wp.plugins;
    const { SelectControl } = wp.components;
    const { PluginDocumentSettingPanel } = wp.editPost;
    const { useSelect, useDispatch } = wp.data;

    registerPlugin('spectator-primary-category', {
        render: function () {

            const postId = useSelect(
                (select) => select('core/editor').getCurrentPostId(),
                []
            );

            const postType = useSelect(
                (select) => {
                    return select('core/editor').getCurrentPostType();
                }, []
            );

            let editPost = useDispatch('core/editor').editPost;
            let savePost = useDispatch('core/editor').savePost;
            let entityRecordEdits = useSelect(
                (select) => select('core').getEditedEntityRecord('postType', postType, postId),
                []
            );
      
            let getEntityRecord = useSelect(
                (select) => select('core/editor').getEditedPostAttribute('meta')
            );

            // console.log(getEntityRecord);

            function handleChange(tokens) {
                let metaEdits = {
                    meta: {
                        ...entityRecordEdits.meta,
                        _spectator_primary_category_metafield: tokens
                    }
                };

                editPost(metaEdits); // Update the Core Data store (client).
                savePost(metaEdits); // Update the WordPress database (server).
            }
            const { categories } = useSelect((select) => {
                const { getEntityRecords } = select('core');

                return {
                    categories: getEntityRecords('taxonomy', 'category'),
                }
            })

            let options = [];
            if (categories) {
                options = categories.map(category => ({ label: category.name, value: category.id }));
                options.unshift({ value: 0, label: 'Select a category' });
                // console.log(options);
            }

            return (
                <PluginDocumentSettingPanel
                    name="spectator-primary-category-panel"
                    title="Add the primary category"
                    className="spectator-primary-category__panel"
                >
                    <SelectControl
                        value={getEntityRecord._spectator_primary_category_metafield}
                        options={options}
                        onChange={handleChange}
                    />
                </PluginDocumentSettingPanel>
            )
        },
        icon: 'airplane' // or false if you do not need an icon
    });
})(window.wp);

wordpress react-redux wordpress-gutenberg
1个回答
1
投票

保存元数据有很多选择。下面的代码片段提出了一种方法。

更新

答案更新了亚伦的更正。应该使用

getEditedEntityRecord
,而不是
getEntityRecordEdits
getEditedEntityRecord 返回数据库中与客户端所做的更改合并的数据,而 getEntityRecordEdits 仅返回在客户端所做的更改。

getEditedEntityRecord 用于确保在 handleChange 进行更新时,对保存到 WordPress

Core Data
数据存储(客户端中的数据存储)的发布元字段所做的更改不会丢失。 getEntityRecord 可以用来取而代之,它将检索存储在数据库(服务器上的数据存储)中的最新值,但不是客户端中所做的最新更改。

const { useSelect, useDispatch } = wp.data; 

...

const postId = useSelect(
    ( select ) => select( 'core/editor' ).getCurrentPostId(),
    []
);

const postType = useSelect(
    ( select ) => {
        return select( 'core/editor' ).getCurrentPostType();
    }, []
);

let editPost = useDispatch( 'core/editor' ).editPost;
let savePost = useDispatch( 'core/editor' ).savePost;
let entityRecordEdits = useSelect(
    ( select ) => select( 'core' ).getEditedEntityRecord( 'postType', postType, postId ),
    []
);

function handleChange( tokens ) {
    let metaEdits = {
        meta: {
            ...entityRecordEdits.meta,
            META_FIELD_NAME: tokens // Replace META_FIELD_NAME with the name of the desired meta field.
        }
    };

    editPost( metaEdits ); // Update the Core Data store (client).
    savePost( metaEdits ); // Update the WordPress database (server).
    setSelectedCategory(tokens); // Missing from original answer.
}

...

let [selectedCategory, setSelectedCategory] = useState([]);

...

<SelectControl
    value={selectedCategory}
    options={options}
    onChange={ handleChange }
/>  

...

editPost 和 savePost

根据所需的页面行为,您可能不需要调用

savePost
.

调用

editPost
(而不是
savePost
)更新WordPress核心数据存储。页面的 Update 按钮中的颜色变化向用户反馈页面上有未保存的更改。您可以让用户点击更新来保存您的WP侧边栏更改以及用户所做的任何其他更改。

调用

savePost
立即保存您的 WP sidebar 更改以及用户对发布元所做的任何其他更改(例如,从更新元的其他页面表单字段)。但是,如果 WP sidebar 对服务器的更新 should not 包括对 Post meta 所做的其他更改,那么应该使用
getEntityRecord
而不是
getEditedEntityRecord
.

© www.soinside.com 2019 - 2024. All rights reserved.