Advertisement
Theme Development

Integrating With WordPress’ UI: Meta Boxes on Custom Pages

by

This is part 2 of a series looking at how your plugin and theme can provide the best user experience by 'fitting in' with WordPress' native UI. This means more than just looking a part of WordPress (which we covered in part one), but where appropriate, mimicking the same workflow that would (hopefully) be familiar to WordPress users. A part of this, is how you structure pages and present information the end user. An incredibly useful tool from both a UI and developer perspective is the meta box. In this tutorial we look at how you can add meta boxes to your own custom admin page.

The use of meta boxes is common in WordPress. It's used on the Widgets, Menus and Dashboard pages - and of course, the post edit screen. They can be a fantastic tool for improving the user experience:

  • They provide a natural grouping of information. On the post edit screen there's a meta box for handling the post's publication, one for each taxonomy, and another for dealing with the post's discussions. Meta boxes visually break up the information into easier to handle chunks.
  • The user decides what's important. The end user can decide which meta boxes appear where, and can completely hide meta boxes that are not relevant to them. Simply put, this allows the user to manipulate the page so that it is arranged in a way that facilitates their workflow.
  • Minimize or remove. A similar point to the one above: irrelevant meta boxes can be minimized or hidden completely.
  • Looks good. On the whole, meta boxes look good. Since they are fairly common in WordPress, other examples of meta boxes (i.e. meta boxes which don't look like the native meta box) just look out of place.

A final point that shouldn't go unnoticed: when implemented properly meta boxes also allow third-parties to add or remove content from your admin page, making your plugin or theme readily extendible.

Please note, I'm not advocating the use of meta boxes for everything - only where it makes sense to do so. As discussed in part one, there are times where WordPress' existing UI is not sufficient or appropriate for what your plugin is trying to do. In these cases, you shouldn't constrain yourself to the admin UI - but you shouldn't ignore it either.


The Page Layout

WordPress is very good at being extended and meta boxes are no exception. The scripts and styles that WordPress uses to position, style, and 'animate' meta boxes is also available to us. Using them means that meta boxes (along with all their 'features') can be added with relatively little code.

However, to take advantage of this, we need to mimic the layout of a WordPress' admin page so that the selectors used in the scripts and styles, apply to our page. Now of course, different pages implement meta boxes differently. For instance, the Dashboard has up to 4 evenly-sized columns of meta boxes, while the post edit page allows only 1 or 2, with one acting as a sidebar. Depending on how you want your page to appear, you'll need to structure your page accordingly. In this tutorial I'll be going through the post edit screen's 1/2-meta box layout. So lets take a look at basic wireframe of an admin page.

.wrap

This element wraps your entire admin page. It adds a margin to the top and right sides to keep the admin page away from the sides of the screen. This should be used on all of your admin pages.

<div class="wrap">
	<!-- Admin page here -->
</div>

Screen Icon

Next is the screen icon. This again should appear on all your admin pages. The mark-up for the screen icon can be generated by using the function screen_icon(). We covered its use in part one of this series. screen_icon('my-id') produces the HTML:

<div id="icon-my-id" class="icon32">
	<br />
</div>

Heading

Next is the page title. The title should be wrapped inside <h2></h2> tags. If appropriate, an 'add new' link can be added inside these tags:

<?php
	printf(
		'<h2> %s <a href="%s" > %s </a></h2>',
		esc_html__('Page Title','plugin_domain'),
		esc_url(admin_url(admin.php?page=my-link-to-add-new)),
		esc_html__('Add New','plugin_domain')
	);
?>

Form

Usually, with meta boxes, you are accepting some form of input from the user. To do this you'll need to wrap the entire page inside a form. In any case it is required to store the meta box preferences (which meta boxes are closed, and the location of the meta boxes).

<form name="my_form" method="post">
	<input type="hidden" name="action" value="some-action">
	<?php wp_nonce_field( 'some-action-nonce' );

	/* Used to save closed meta boxes and their order */
	wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
	wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>

	<!-- Rest of admin page here -->

</form>

#poststuff

This element wraps the meta box holder. It's an important element as WordPress uses this in targeting its styles and scripts.

<div id="poststuff">
	<!-- #post-body .metabox-holder goes here -->
</div>

#post-body

This element acts as the meta box holder. It has two important classes:

metabox-holder and columns-*. The second of these specifies the layout of the page (whether it has 1 or 2 columns). The user-specified layout option can be obtained with get_current_screen()->get_columns(). In the following we use this to add the class columns-1 or columns-2 appropriately (with the latter as default).

<div id="post-body" class="metabox-holder columns-<?php echo 1 == get_current_screen()->get_columns() ? '1' : '2'; ?>">
	<!-- meta box containers here -->
</div>

The Meta Box Containers Inside #post-body

There are two meta box containers, which act as the 'columns' of meta boxes. The first, .postbox-container-1, acts as the sidebar in the 2-column layout, and in the 1-column layout sits just above the second meta box container. Then there is #post-body-content. This (optional) element doesn't contain any meta boxes, but contains any content that you want to sit at the top of the page, and not be moveable. In the post edit screen, for example, it contains the post title, and TinyMCE editor.

To print the meta boxes inside the relevant container we use the do_meta_boxes function which takes three arguments:

  • $screen - The screen ID (or we can use an empty string to use the current screen ID).
  • $context - This a string identifier used when registering the meta box. This can be anything, but should be descriptive (for example 'side' and 'normal'). This allows you to define the default position and order of meta boxes.
  • $object - This is passed to the meta box's callback as the first argument, and is usually the object being edited (for example a post object, on the post edit screen). If this isn't relevant for your admin page, you can pass null.
	<div id="post-body-content">
		<!-- #post-body-content -->
	</div>

	<div id="postbox-container-1" class="postbox-container">
		<?php do_meta_boxes('','side',$object); ?>
	</div>

	<div id="postbox-container-2" class="postbox-container">
		<?php do_meta_boxes('','normal',$object); ?>
		<?php do_meta_boxes('','advanced',$object); ?>
	</div>

Example Layout

	<div class="wrap">

		<?php screen_icon(); ?>

		<h2><?php esc_html_e('Page Title','domain'); ?></h2>

		<form name="my_form" method="post">
			<input type="hidden" name="action" value="some-action">
			<?php wp_nonce_field( 'some-action-nonce' );

			/* Used to save closed meta boxes and their order */
			wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
			wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>

			<div id="poststuff">

				<div id="post-body" class="metabox-holder columns-<?php echo 1 == get_current_screen()->get_columns() ? '1' : '2'; ?>">

					<div id="post-body-content">
						<!-- #post-body-content -->
					</div>

					<div id="postbox-container-1" class="postbox-container">
						<?php do_meta_boxes('','side',null); ?>
					</div>

					<div id="postbox-container-2" class="postbox-container">
						<?php do_meta_boxes('','normal',null); ?>
						<?php do_meta_boxes('','advanced',null); ?>
					</div>

				</div> <!-- #post-body -->

			</div> <!-- #poststuff -->

		</form>

	</div><!-- .wrap -->

Adding Meta Boxes & Screen Options

Now we have the page structure we now want us (or any third party) to be able to add meta boxes to the page. We'd also like to load up the necessary JavaScript that allows these meta boxes to be minimised, hidden or moved.

To allow meta boxes to be added we need to fire two hooks. The first:

add_meta_box_{screen_id}

Passes the object being edited (or null). The second:

add_meta_box

Passes two variables: the screen ID and the object being edited. Users can then hook on these actions and add their meta boxes to the page.

Next we want to load the WordPress script postbox.js. This script allows the user to move, minimise or close meta boxes (and saves their preferences). The script needs to be initialised so we'll need to print one line of javascript in the footer to do this.

Finally, we add a screen option allowing the user to switch between the one and two column layout. Screen options allowing the user to hide meta boxes are automatically added. We'll use the load-{$pagenow} hook to fire our callback only on the appropriate page. For custom admin pages, $pagenow is the screen ID.

<?php
/* Throughout $screen_id is assumed to hold the screen ID */

/* Add callbacks for this screen only. */
add_action('load-'.$screen_id, 'wptuts_add_screen_meta_boxes');
add_action('admin_footer-'.$screen_id,'wptuts_print_script_in_footer');

/*
 * Actions to be taken prior to page loading. This is after headers have been set.
 * @uses load-$hook
 */
function wptuts_add_screen_meta_boxes() {

	/* Trigger the add_meta_boxes hooks to allow meta boxes to be added */
	do_action('add_meta_boxes_'.$screen_id, null);
	do_action('add_meta_boxes', $screen_id, null);

	/* Enqueue WordPress' script for handling the meta boxes */
	wp_enqueue_script('postbox');

	/* Add screen option: user can choose between 1 or 2 columns (default 2) */
	add_screen_option('layout_columns', array('max' => 2, 'default' => 2) );
}

/* Prints script in footer. This 'initialises' the meta boxes */
function wptuts_print_script_in_footer() {
	?>
	<script>jQuery(document).ready(function(){ postboxes.add_postbox_toggles(pagenow); });</script>
	<?php
}
?>

All that remains is to add the meta boxes.


Adding Meta Boxes to the Page

Normally meta boxes can be added using the add_meta_boxes or, better yet, the add_meta_boxes_{post_type} hooks. More generally post type can be thought of as the screen ID. We've triggered these hooks inside the wptuts_add_screen_meta_boxes() function above. All that remains is to hook onto these actions and use the add_meta_box() function.

/* Throughout $screen_id is assumed to hold the screen ID */

add_action('add_meta_boxes_'.$screen_id,'wptuts_add_my_meta_box');
function wptuts_add_my_meta_box() {
	add_meta_box(
		'my_meta_box_id', //Meta box ID
		__('My Meta Box','plugin_domain'), //Meta box Title
		'wptuts_my_meta_box_callback', //Callback defining the plugin's innards
		$screen_id, // Screen to which to add the meta box
		'normal' // Context
	);
}

Code

You can download a simple admin page class based on this tutorial from GitHub.

Related Posts
  • Code
    Theme Development
    Creating a WordPress Theme from Static HTML - Creating a Page TemplateCreating wordpress theme from html 400
    So far in this series, I've shown you how to create a fully functioning WordPress theme from static HTML. We've covered the following steps: preparing your markup for WordPress converting your HTML to PHP and splitting your file into template files editing the stylesheet and uploading your theme to WordPress adding a loop to your index file adding meta tags, the wp_head hook and the site title and description to your header file adding a navigation menu adding widget areas to the header and sidebar adding widget areas, a colophon and the wp_footer hook to the footer file. At the moment, your theme only has one template file for displaying content—the index.php file. A powerful feature of WordPress is the ability to use template files for different kinds of content.Read More…
  • Code
    Theme Development
    Creating a WordPress Theme From Static HTML: The Footer FileCreating wordpress theme from html 400
    In this series, you've been learning how to create a WordPress theme form static HTML. Up to this point, you have: prepared your markup for WordPress converted your HTML to PHP and split your file into template files edited the stylesheet and uploaded your theme to WordPress added a loop to your index file added meta tags, the wp_head hook and the site title and description to your header file added a navigation menu added widget areas to the header and sidebar. Read More…
  • Code
    Theme Development
    Creating a WordPress Theme from Static HTML - Adding WidgetsCreating wordpress theme from html 400
    In this series, you've learned how to convert a static HTML file to a WordPress theme and edit the header file. So far you've: prepared your markup for WordPress converted your HTML to PHP and split your file into template files edited the stylesheet and uploaded your theme to WordPress added a loop to your index file added meta tags, the wp_head hook and the site title and description to your header file added a navigation menu. Read More…
  • Code
    Theme Development
    Creating a WordPress Theme From Static HTML: Creating Template FilesCreating wordpress theme from html 400
    In the first part of this series, I showed you how to prepare your HTML and CSS files for WordPress, ensuring the structure would work, the code was valid and that the correct classes were being used. In this tutorial you'll learn how to take your index.html file and split it up into a set of template files for use by WordPress.Read More…
  • Code
    Theme Development
    Creating a WordPress Theme From Static HTML: Preparing the MarkupCreating wordpress theme from html 400
    Last year I did a small (and admittedly very un-scientific) survey among other WordPress developers. What I wanted to know was this: When they built their first WordPress theme, how did they do it? Did they hack an existing theme or did they start with their own static HTML and turn it into a theme? The majority of people I spoke to used the second approach - they were all experienced frontend developers who had built sites using HTML and CSS, and found it easiest to take their existing HTML files and convert them to a theme. Two of the people I spoke to were lecturers or teachers, and told me that this is the approach they use with students. So in this series I'm going to show you how to do just that.Read More…
  • Code
    Creative Coding
    Customizing the WordPress Admin: Help TextCustomize wordpress admin rachel 400
    In Part 2 of this tutorial, I showed you how to add custom metaboxes to the WordPress dashboard, which you can use to provide help text for your clients or users. But what if you want to provide help text on individual editing screens? In this tutorial, I'll show you how to do just that.Read More…