For my next (still forthcoming) version of my WordPress calendar plugin, My Calendar, I had a need to add custom screen options to a couple of editing screens. Now, there’s a great tutorial on adding screen options by Chris Marslender that I found very useful.
It is, however, incomplete.
Now, if what you want to do is add one basic control, that tutorial is definitely going to get you where you need to go. It’s simple, straightforward, and accurate. However, it has one tiny error and one large omission.
The tiny error is simple: for saving the option, the tutorial specifies this code:
add_filter('set-screen-option', 'cmi_set_option', 10, 3);
function cmi_set_option($status, $option, $value) {
if ( 'cmi_movies_per_page' == $option ) return $value;
}
This will work, for a single field. But, if you add two, you’ll notice that this filter *prevents* any other screen option value from being sent if it is not equal to ‘cmi_movies_per_page’. It doesn’t stop any of the default screen options, which are all whitelisted in the WordPress function handling updating options. When you add another custom function, however…no go.
Easy fix:
add_filter('set-screen-option', 'cmi_set_option', 10, 3);
function cmi_set_option($status, $option, $value) {
return $value;
}
Because the value being returned by the function named is very simple; just an integer; there’s no need to filter it in any way; just make sure it gets passed to the function and then saved in the user’s meta data.
Adding custom controls to Screen Options
That was the error. The omission (which is entirely fair, because it was already a long tutorial — no need to cover everything!) is about adding custom controls and saving their data. Because, in fact, you can add any control to the screen options — you’re not constrained to the standard control types that WordPress uses.
For consistency, I’m basing my settings on the same type of data used in Chris’s tutorial; I think this will make it easier to compare the two tutorials and make use of them together.
First, getting some fields into your screen options. This can be ignored when using the default screen options, because they’ll provide your HTML (HyperText Markup Language) controls for you. But you can attach your own custom controls through the filter screen_settings
.
add_filter('screen_settings', 'cmi_show_screen_options', 10, 2 );
The function itself needs to do a handful of things:
- Define what it will return, whether it’s the desired screen or not.
- Determine whether it’s on the right screen for the controls.
- Return the form fields (the form itself is automatic)
The form fields must include an array of inputs named wp_screen_options[option]
and wp_screen_options[value]
, or the submission will be ignored. As you’ll see further along, the option
parameter is the important one; you need value
to be present, but you don’t necessarily need to use it. That’s a choice, however, depending on what you’re doing with the data.
The current screen is passed to the screen settings function in an object variable of arguments, here called ‘$args’. You can test against your current screen using the $args->base
member.
function cmi_show_screen_options( $status, $args ) {
$return = $status;
if ( $args->base == 'toplevel_page_my-calendar' ) {
$button = get_submit_button( __( 'Apply' ), 'button', 'screen-options-apply', false );
$return .= "
<fieldset>
<legend>Show Columns</legend>
<div class='metabox-prefs'>
<div><input type='hidden' name='wp_screen_options[option]' value='cmi_show_columns' /></div>
<div><input type='hidden' name='wp_screen_options[value]' value='yes' /></div>
<div class='cmi_custom_fields'>
<label for='cmi_producer'><input type='checkbox' value='on' name='cmi_columns[]' id='cmi_producer' /> Producer</label>
<label for='cmi_director'><input type='checkbox' value='on' name='cmi_columns[]' id='cmi_director' /> Director</label>
</div>
</div>
</fieldset>
<br class='clear'>
$button";
}
return $return;
}
In this example, I’m passing data using an arbitrarily named field called cmi_columns
. I’m hypothesizing this as a group of controls to limit which fields you’re showing on a plug-in page.
Saving your Custom Screen Options
You’ll be using the same filter as in the other tutorial to save your data:
add_filter('set-screen-option', 'cmi_set_screen_options', 11, 3);
In the function itself, you can manipulate the POST data sent from your custom screen options however you wish. You can dance with it, change it, ignore it; whatever is relevant for you. If you need to interpret the data sent and use it in a way other than that directly posted, here’s where you can do it. Not in this example, however — which simply takes the posted data, and returns it to be saved in the user data.
function cmi_set_screen_options($status, $option, $value) {
if ( 'cmi_show_columns' == $option ) {
$value = $_POST['cmi_columns'];
}
return $value;
}
That’s it. Value saved and passed.
What’s important in this tutorial?
If you’re trying to use the information from Chris’s tutorial to create multiple screen options, you’re going to get a little frustrated when the second one just won’t save. That’s because of the failure to return a value in the filter unless the specific field is passed. If you need to pass a type of data other than defaults, that tutorial doesn’t cover it. So here you are. Enjoy!
Joe Dolson
Thanks for sharing, Sam!
sam perrow
Thanks for the info! I ran into one problem, which is when the plugin has just been activated and the user has not entered a per_page value, this can cause a problem when creating admin tables, because the db will limit the number of rows by the per_page value. And if the user has not explicitly set a value, the admin table can’t be produced because per_page is an empty string. I fixed this by adding:
if ( $per_page == ”) {
settype( $per_page, “int”);
$per_page = 10;
}
and it fixed my dilemma.
Spencer Hill
Oh duh! Haha, thank you!
Joe Dolson
That’s actually considerably easier. If you use the filters for adding a custom column, WordPress will automatically add a screen option for turning that column on and off in your screen options, so all you need to look up is how to add a custom column.
There’s a great tutorial by Justin Tadlock that covers this: Custom Columns for Custom Post Types. Give it a read!
Spencer Hill
Thanks for the tutorial. I’m using the ACF Plugin to create a Custom Field for a Custom Post Type and I’m wanting to have a Custom Field (called “Telephone Number”) displayed as a Column when it’s checked in Screen Options (this is all from the overview/browse section where you see all your Posts).
Any chance you can share how to achieve this? Thanks?