2015-02-07

In this tutorial I want to explain Step by Step How To Create WordPress Settings/Options Page With Meta Box, like what you see in this screenshot:

WordPress have a decent Settings API and it offer a lot flexibility in design. Several plugins do “wild” things in their Settings Page, However for better user experience it’s best to use seamless design (blended) with other admin UI design.

One of my favorite admin UI element is Meta Box. Not only because meta box have an easy to use Meta Box API (so we can easily create meta boxes), but it also have user preference options where user can reorder (drag-and-drop) the position, toggle open/close meta boxes. and even changing Screen Layout to 1 or 2 column using “Screen Options”.

Benefit in using Meta Box in Settings Page:

Nice UI : Neatly Group Complex Settings.

Minimum Design Time : WordPress already have the design.

Easy to use : because user already familiar with how the panel works.

Extend-Ability : Other developer can easily extend our plugins and add options with familiar API.

So Let’s Start !

Wait, before we start, maybe it’s better if you download the example plugin to easily follow this tutorial. I host it at Github. So, fork if you must

Fork @GitHub

Download ZIP

In this tutorial, I will also assume that you already familiar with WordPress Settings API and WordPress Meta Box API.

Prepare Our Plugin

Create the plugin folder, and create simple plugin header to start.

Create Blank Settings Page

The function fx_smb_settings_setup() is to register our settings and add settings in admin menu. And we will use the utility function fx_smb_setings_page_id() to refer our settings page, for example to enqueue scripts.

I use admin menu name “Meta Box” just because (no reason) and add in menu position 5, which is after the “Dashboard” Menu to make it easier to display it in the screenshot

After we have this function in place we will have a blank settings page ready.

Create Settings Page

In our (currently blank) fx_smb_settings_page() function we will add our HTML markup for the settings and use the “Post Edit Screen” Markup.

You can check “wp-admin/edit-form-advanced.php” if you  want to learn more about the HTML structure and functions. I simplify the markup in post edit screen and only use what we need.

After we add this code in our function we will still see the empty settings page, but now we have a settings title, “Settings Meta Box” (in H2) at the top of our settings page.

Use Settings API Functions

As you can see above, I use several function in Settings API you already familiar with:

settings_errors() : this is to display “Updated” and “Error” message when we save or reset our settings.

settings_fields(): this is needed in Settings API, this is where WordPress handle settings we register to this page using register_setting() function.

But we are not using add_settings_field() and add_settings_section() function, because we are going to add our settings using Meta Box API.

Enable Meta Box in Settings Page

So to replace add_settings_field() and add_settings_section() functionality, we need to enable Meta Boxes API in our settings, and to do this we use do_meta_boxes() function:

There’s three instance of do_meta_boxes() for each meta box context / location ( “side”, “normal”, and “advance” ), and we use global $hook_suffix as the page identifier.

Usually when we add our meta box in Post Edit Screen, we define the page using post type as identifier ( “post”, “page”, or “our-cpt” ), and now if we want to add meta boxes in this settings page, we simply change the page with our settings page $hook_suffix. and it’s the same return value with our utility function fx_smb_setings_page_id().

The function do_meta_boxes() will do nothing, To enable it we need to add add_meta_boxes action hook, as you see we have this code: do_action( 'add_meta_boxes', $hook_suffix ); at the top of the page.

We also add an utility hook fx_smb_settings_page_init at the top of the page and we will use this later.

Enable Meta Boxes Functionality

Adding meta box is not enough, we also need to enable Meta Box functionality, such as “reorder meta box” using drag and drop, “toggle meta box“, and change the “screen layout“. This functionality require several script, and we need to add these scripts in our Settings Page.

Let’s back to fx_smb_settings_setup() function to add scripts needed and set number of available screen layout column.

and the functions:

To save this user preference in user meta, we need to add nonce in our settings page, If you check fx_smb_settings_page() function there’s two nonce field added, one for meta box toggle, and one for meta box order. We need to add it inside the form, and I add it after settings_fields( 'fx_smb' ); function:

And after we add that, we will see a working meta box area with screen layout option enabled.

Note: WordPress only add border to “Side” Meta Box Area (context), And no “screen layout” selected yet.

Create Save Options Meta Box

In Post Edit Screen, we have “Publish” meta box, and we are going to add similar meta box to Save our options.

As you can see, we use “submitdiv” as Meta Box ID, this is the same ID as “Publish” Meta Box we see in Post Edit Screen, We also reuse HTML elements in “Publish” Meta Box. This provide several benefit:

No need to style it, it will use the same design as “Publish” Meta Box.

It’s automatically excluded in “Show on screen” check boxes in “Screen Options” toggle, so user can’t hide this meta box.

The “Save” Option functionality is working at this point, because WordPress Settings API have this build-in, so the “Save” button will work. But the “Reset Settings” link is not yet working. We need to build this functionality our-self, because WordPress do not have this functionality. This feature is optional,

We use add_query_arg() function to build URL structure for “Reset Settings” link, and the out put will be:

So it’s just the URL to our settings page with additional parameter to reset settings and nonce to make it secure. This URL still do nothing, To actually reset the settings we are going to use our utility hook  “fx_smb_settings_page_init” in fx_smb_settings_page() function:

It’s a straightforward function:

Check “reset_settings” action request.

Check the user capability

Verify our nonce,

If everything is good, delete our option and display “Updated” notification.

If something goes wrong, do nothing and display “Error” notification.

We use delete_option() instead of saving the default option in database. I consider this is important to actually remove the entry from database instead of saving the default because:

Cleaner database.

Use sane defaults in our function.

I explain this because there’s a popular settings framework doing it wrong and save the default option instead of deleting the option in their “reset” functionality.

Fine-tuning “Save Options” Meta Box:

If you check in our “Save Options” meta box function fx_smb_submit_meta_box(). Above the submit button, there’s a “spinner” empty span. This span as default is hidden using CSS, and when we submit our form, we need to display it. This is to notify user that the submit button is working and processing the data. We also need to create a pop-up confirmation if user want to reset the settings. We can add  simple javascript to do this in fx_smb_footer_scripts().

And now we have our “Save Option” meta box working.

Create Our Meta Box Settings

Now, we can create our Settings input using Meta Box API. It’s just simple example and we only create one text field.

But first, let’s back to fx_smb_settings_setup() function where we register our setting.

So we are going to save our option in “fx_smb_basic”, and the function we use to sanitize the option is “fx_smb_basic_sanitize”.

With this data, Let’s create options!

Very simple right?

In the example I only create one text field, and it is saved in “fx_smb_basic” option name. If you want to create several field in the meta box you can also save them in single data entry as array, This can make the database leaner.

Database Schema Notes:

If you need more than one meta boxes, It is better to use register_setting() for each meta boxes. That means, save each meta box data in different option_name.

It will offer more flexibility when we need to create / remove additional meta boxes/settings.

If you save all meta boxes data in one data entry and In the future you need to remove additional meta boxes, when user save the data, all previous data will be lost (sometimes this is not wanted). This will also make the database structure more manageable.

Example use case: If we create an add-on plugin for the “main” plugin. And this add-on create additional meta box options.

Design Notes:

If you want to prettify the meta box design, always remember:

WordPress Admin is Responsive, make sure user can easily input the data using small screen device.

User can change meta box order, and drag the meta box in “Side” location (context). Make sure all field look neat there too.

Check out WordPress default meta boxes, there’s several HTML class you can use, for example “howto” class for explaining a field.

Well, that’s it. If you have questions or suggestions, leave a comment. If you think it will be useful for others, share

Show more