wordpress 当selectControl更改时, gutenberg 将数据保存到post meta字段

c86crjj0  于 2023-03-29  发布在  WordPress
关注(0)|答案(1)|浏览(142)

我是React和JSX的新手,一直在WP侧边栏中的选择菜单下拉字段上工作。这个选择菜单显示了当前添加的帖子类别,这部分工作得很好。
我遇到的问题是如何保存这个选择,以及如何用选择控制区域中的选择选项更新post meta字段。
我在functions.php文件中使用register_meta创建了一个post 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帮助我理解了这是如何工作的,我能够更新 meta字段并显示结果。下面是最终使用的代码:

/**
 * 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);
k97glaaz

k97glaaz1#

保存 meta数据有很多种方法,下面的代码片段给出了一种方法。

更新

使用Aaron的更正更新了答案,应该使用getEditedEntityRecord,而不是getEntityRecordEdits。getEditedEntityRecord返回数据库中的数据,并与客户端中的更改合并,而getEntityRecordEdits只返回客户端中的更改。

getEditedEntityRecord用于确保当handleChange进行更新时,对保存到WordPress Core Data 数据存储(客户端中的数据存储)的post meta字段所做的更改不会丢失。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核心数据存储。页面的更新按钮中的颜色更改给予用户反馈页面上有未保存的更改。您可以让用户单击更新来保存您的 *WP侧边栏 * 更改沿着用户所做的任何其他更改。
调用savePost会立即保存您的 *WP侧边栏 * 更改沿着用户对Post meta所做的任何其他更改(例如,从其他更新meta的页面表单字段)。但是,如果 *WP侧边栏 * 更新到服务器不应该包括对Post meta所做的其他更改,则应该使用getEntityRecord而不是getEditedEntityRecord

相关问题