PMG Digital Made for Humans

Adding WordPress Screen Options

5 MINUTE READ | June 11, 2012

Adding WordPress Screen Options

Author's headshot

Christopher Davis

Christopher Davis has written this article. More details coming soon.

WordPress has built in support for things called screen options. If you take a look at the top of the post editing screen, for instance, you’ll see two tabs. One for help and one for the screen options.

This tutorial will cover adding your own screen options. We’re going to give our users the option of change the default “Enter Title Here” text on new posts.

The WP_Screen class has a method called add_option. There’s also a wrapper function for that called add_screen_option. Both of these are deceptive: they appear to add support automatically – maybe you can specify a callback function to render your fields and titles and such?

That’s not the case. add_screen_option only works for a set of predefined screen options (like per_page). Adding any custom options takes a bit more work.

To add our field, we’ll need to hook into screen_settings. Before we do that, let’s setup a container class to hold all of our functionality. There are a few class constants in here, we’ll use later on.

class PMG_Options_Tut

{

/**

* The ajax action

*/

const ACTION = ‘pmg_sotut_save’;

/**

* Our nonce name

*/

const NONCE = ‘pmg_sotut_nonce’;

public static function init()

{

// we’ll add actions here

}

} // end class

PMG_Options_Tut::init();

Unfortunately, screen_settings fires on every admin page. So we need to figure out a way to fire our hook only the post-new.php page where it matters. To do that, we’ll hook into load-post-new.php and from there we can add filters as needed.

public static function init()

{

add_action(

‘load-post-new.php’,

array(get_class(), ‘load’)

);

}

And of course, our load method. There are several other filters/actions added in here that we’ll cover later on.

/**

* Hooked into ‘load-post-new.php’. Adds an option and

* hooks into a few other actions/filters

*

* @access public

* @return null

*/

public static function load()

{

add_filter(

‘screen_settings’,

array(get_class(), ‘add_field’),

10,

2

);

add_action(

‘admin_head’,

array(get_class(), ‘head’)

);

add_filter(

‘enter_title_here’,

array(get_class(), ‘title’)

);

}

The function hooked into screen_settings will get two arguments, the return value (a string with other custom fields, etc) and the current WP_Screen object.

<?php

/**

* Hooked into ‘screen_settings’. Adds the field to the settings area

*

* @access public

* @return string The settings fields

*/

public static function add_field($rv, $screen)

{

$val = get_user_option(

sprintf(‘default_title_%s’, sanitize_key($screen->id)),

get_current_user_id()

);

$rv .= ‘’;

$rv .= ‘’ . __(‘Default Title’) . ‘’;

$rv .= ‘<input type=”text” class=”normal-text” id=”pmg-sotut-field” ‘ .

‘value=”‘ . esc_attr($val) . ‘” />’;

$rv .= wp_nonce_field(self::NONCE, self::NONCE, false, false);

$rv .= ‘’;

return $rv;

}

There’s a lot of stuff going on in this method, so let’s break it down. First, we’ll get the current users setting for default_title_{$screen->id} with get_user_option. Next we build our field and add a nonce that we’ll use in ajax calls. Finally we just return the initial string with our field appended.

That wraps up actually getting the field to display. Now let’s save the data!

WordPress saves things like meta box display and other screen options via Ajax calls. Which means, of course, that we need to write our own AJAX methods. Step one, of course, is actually getting an AJAX request to fire when our custom field loses focus. So we’ll hook into admin_head – you can see that in the load method above – and spit out some JavaScript:

<?php

/**

* Hooked into ‘admin_head’. Spits out some JS to save the info

*

* @access public

* @return null

*/

public static function head()

{

?>

<script type=”text/javascript”>

jQuery(document).ready(function() {

jQuery(‘input#pmg-sotut-field’).blur(function() {

jQuery.post(

ajaxurl,

{

title: jQuery(this).val(),

nonce: jQuery(‘input#<?php echo esc_js(self::NONCE); ?>’).val(),

screen: ‘<?php echo esc_js(get_current_screen()->id); ?>’,

action: ‘<?php echo self::ACTION; ?>’

}

);

});

});

</script>

<?php

The jQuery above just makes an ajax request with the title we want, the nonce, and the current screen id. The server side portion of this is that we need to hook into wp_ajax_{$action} and handle saving everything. Let’s modify our init function to include that hook.

}

<?php

* Init function. Called from outside the class. Adds actions and such.

*

* @access public

* @return null

*/

public static function init()

{

add_action(

‘load-post-new.php’,

array(get_class(), ‘load’)

);

add_action(

‘wp_ajax_’ . self::ACTION,

array(get_class(), ‘ajax’)

);

}

And the function that handles ajax request:

/**

* Hooked into ‘wp_ajax_self::ACTION’  Handles saving the fields and such

*

* @access public

* @return null

*/

public static function ajax()

{

check_ajax_referer(self::NONCE, ‘nonce’);

$screen = isset($_POST[‘screen’]) ? $_POST[‘screen’] : false;

$title = isset($_POST[‘title’]) ? $_POST[‘title’] : false;

if(!$screen || !($user = wp_get_current_user()))

{

die(0);

}

if(!$screen = sanitize_key($screen))

{

die(0);

}

update_user_option(

$user->ID,

“default_title_{$screen}”,

esc_attr(strip_tags($title))

);

die(‘1’);

}

First this checks to make sure our nonce validates and that we have the $screen variable we need. It also fetches the current, logged in user. Finally a call to update_user_option saves the title.

The final bit of all this is hooking into enter_title_here and replace the value with the users text.

/**

* Hooked into ‘enter_title_here’. Replaces the title with the user’s

* preference (if it exists).

*

* @access public

* @return string The Default title

*/

public static function title($t)

{

if(!$user = wp_get_current_user())

return $t;

$id = sanitize_key(get_current_screen()->id);

if($title = get_user_option(“default_title_{$id}”, $user->ID))

{

$t = esc_attr($title);

}

return $t;

}

Stay in touch

Bringing news to you

Subscribe to our newsletter

By clicking and subscribing, you agree to our Terms of Service and Privacy Policy

That thats it!  After updating the option, the next view of post-new.php should use the new default. You can see all this code together on github.


Related Content

thumbnail image

AlliPMG CultureCampaigns & Client WorkCompany NewsDigital MarketingData & Technology

PMG Innovation Challenge Inspires New Alli Technology Solutions

4 MINUTES READ | November 2, 2021

thumbnail image

Applying Function Options to Domain Entities in Go

11 MINUTES READ | October 21, 2019

thumbnail image

My Experience Teaching Through Jupyter Notebooks

4 MINUTES READ | September 21, 2019

thumbnail image

Working with an Automation Mindset

5 MINUTES READ | August 22, 2019

thumbnail image

3 Tips for Showing Value in the Tech You Build

5 MINUTES READ | April 24, 2019

thumbnail image

Testing React

13 MINUTES READ | March 12, 2019

thumbnail image

A Beginner’s Experience with Terraform

4 MINUTES READ | December 20, 2018

ALL POSTS