20

I am trying to add a new component panel under document tab, like categories, featured image etc.

enter image description here

daniyalahmad
  • 2,703
  • 5
  • 24
  • 50

5 Answers5

10

They've added the PluginDocumentSettingPanel SlotFill now.

const { registerPlugin } = wp.plugins
const { PluginDocumentSettingPanel } = wp.editPost
 
const PluginDocumentSettingPanelDemo = () => (
    <PluginDocumentSettingPanel
        name="custom-panel"
        title="Custom Panel"
        className="custom-panel"
    >
        Custom Panel Contents
    </PluginDocumentSettingPanel>
)
registerPlugin('plugin-document-setting-panel-demo', {
    render: PluginDocumentSettingPanelDemo
})
T.Todua
  • 44,747
  • 17
  • 195
  • 185
Rice_Crisp
  • 1,061
  • 1
  • 13
  • 30
  • I am using this kind of setup but when I add a textcontrol it isn't working properly. When I try to change the value in the input field it isn't displayed. It stays at the init value. Maybe because I don't have props and stuff in this setup. Can you tell me how manage that since it workings different than the block inspector? – Insomnia88 Oct 29 '19 at 12:40
  • Do you know how I could add this below all the other document setting options? It currently loads above 'Revisions' and I'd like it to appear under 'Featured Image' – AndreVitorio Mar 09 '21 at 22:11
7

add_meta_box will do the trick, but only if you add the context-argument with a value of 'side':

add_meta_box(
    'box-id-here',
    'Box Title Here',
    'createBoxHtml',
    'post',
    'side' ); // <-- this is important

Arrrh, two days for nothing!


Old answer

According to this tutorial, we can add our custom sidebar and fill it with customized form inputs.

Here is a working example in a React JSX version. This adds a meta field country:

const { registerPlugin } = wp.plugins;
const { PluginSidebar } = wp.editPost;
const { TextControl } = wp.components;
const { withSelect, withDispatch } = wp.data;

// Customized TextControl
const CustomMetaField = withDispatch( ( dispatch, props ) => {
    return {
        updateMetaValue: ( v ) => {
            dispatch( 'core/editor' ).editPost( {
                meta: {
                    [ props.metaFieldName ]: v
                }
            });
        }
    };
})( withSelect( ( select, props ) => {
    return {
        [ props.metaFieldName ]: select( 'core/editor' ).getEditedPostAttribute( 'meta' )[ props.metaFieldName ]
    };
} )( ( props ) => (
    <TextControl
        value={props[ props.metaFieldName ] }
        label="Country"
        onChange={( v ) => {
            props.updateMetaValue( v );
        }}
    /> )
) );


// Our custom sidebar
registerPlugin( 'custom-sidebar', {
    render() {
        return (
            <PluginSidebar
                name="project-meta-sidebar"
                title="Project Meta">
                <div className="plugin-sidebar-content">
                    <CustomMetaField metaFieldName="country" />
                </div>
            </PluginSidebar>
        );
    },
} );

And in PHP, register the meta field in the init-hook:

register_meta( 'post', 'country', [
    'show_in_rest' => TRUE,
    'single' => TRUE,
    'type' => 'string'
] );

I know:

This is still not the required solution, but nearly.

jla
  • 2,867
  • 3
  • 20
  • 35
uruk
  • 849
  • 1
  • 10
  • 18
2

You can add this code to your function.php. This code create new tab and add text field to this tab. Text field save to database like custom field in post_meta table and you can output this like default WP post meta.
1. Create tab Настройки UTM.
2. Create custom text field utm_post_class
3. To output in website use $utm = get_post_meta( $post->ID, 'utm_post_class', true );

//Article UTM Link
add_action( 'load-post.php', 'utm_post_meta_boxes_setup' );
add_action( 'load-post-new.php', 'utm_post_meta_boxes_setup' );

function utm_post_meta_boxes_setup() {
    add_action( 'add_meta_boxes', 'utm_add_post_meta_boxes' );
    add_action( 'save_post', 'utm_save_post_class_meta', 10, 2 );
}

function utm_add_post_meta_boxes() {
    add_meta_box(
        'utm-post-class',
        'Настройки UTM',
        'utm_post_class_meta_box',
        'post',
        'side',
        'default'
    );
}

function utm_post_class_meta_box( $post ) {
    wp_nonce_field( basename( __FILE__ ), 'utm_post_class_nonce' );?>

    <div class="components-base-control editor-post-excerpt__textarea">
        <div class="components-base-control__field">
            <label class="components-base-control__label" for="utm-post-class">UTM ссылка (необязательно)</label>
            <input type="text" name="utm-post-class" id="utm-post-class" class="edit-post-post-schedule" value="<?php echo esc_attr( get_post_meta( $post->ID, 'utm_post_class', true ) ); ?>">
        </div>
    </div>
<?php }

function utm_save_post_class_meta( $post_id, $post ) {

    if ( !isset( $_POST['utm_post_class_nonce'] ) || !wp_verify_nonce( $_POST['utm_post_class_nonce'], basename( __FILE__ ) ) )
        return $post_id;

    $post_type = get_post_type_object( $post->post_type );
    if ( !current_user_can( $post_type->cap->edit_post, $post_id ) )
        return $post_id;

    $new_meta_value = ( isset( $_POST['utm-post-class'] ) ? $_POST['utm-post-class'] : '' );
    $meta_key = 'utm_post_class';
    $meta_value = get_post_meta( $post_id, $meta_key, true );

    if ( $new_meta_value && '' == $meta_value )
        add_post_meta( $post_id, $meta_key, $new_meta_value, true );
    elseif ( $new_meta_value && $new_meta_value != $meta_value )
        update_post_meta( $post_id, $meta_key, $new_meta_value );
    elseif ( '' == $new_meta_value && $meta_value )
        delete_post_meta( $post_id, $meta_key, $meta_value );
}
0

add_meta_box adds a new panel there for the gutenberg editor

Swopnil Dangol
  • 624
  • 3
  • 7
  • 1
    This adds your old meta field to the sidebar. Do you know how to implement a new React-based box? – Rice_Crisp Jan 22 '19 at 15:52
  • One could add a custom sidebar, see https://github.com/WordPress/gutenberg/blob/master/docs/designers-developers/developers/tutorials/sidebar-tutorial/plugin-sidebar-0.md – uruk Jan 24 '19 at 20:31
0

You can now use the newer useSelect and useDispatch custom hooks. They are similar to withSelect and withDispatch, but utilize custom hooks from React 16.8 for a slightly more concise dev experience:

(Also, using @wordpress/scripts, so the imports are from the npm packages instead of the wp object directly, but either would work.)

import { __ } from '@wordpress/i18n';
import { useSelect, useDispatch } from '@wordpress/data';
import { PluginDocumentSettingPanel } from '@wordpress/edit-post';
import { TextControl } from '@wordpress/components';

const TextController = (props) => {
  const meta = useSelect(
    (select) =>
      select('core/editor').getEditedPostAttribute('meta')['_myprefix_text_metafield']
  );
  const { editPost } = useDispatch('core/editor');
  return (
    <TextControl
      label={__("Text Meta", "textdomain")}
      value={meta}
      onChange={(value) => editPost({ meta: { _myprefix_text_metafield: value } })}
    />
  );
};

const PluginDocumentSettingPanelDemo = () => {
  return (
    <PluginDocumentSettingPanel
      name="custom-panel"
      title="Custom Panel"
      className="custom-panel"
    >
      <TextController />
    </PluginDocumentSettingPanel>
  );
};

export default PluginDocumentSettingPanelDemo;

Along with registering your meta field as usual:

function myprefix_register_meta()
{
    register_post_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');
        }
    ));
}
add_action('init', 'myprefix_register_meta');

And make sure if using for a custom post type, that you include custom-fields in the array of supports:

'supports' => array('title', 'editor', 'thumbnail', 'revisions', 'custom-fields'),

Hopefully that helps.

dmoz
  • 643
  • 8
  • 24