71

I have two simple functions that load stuff using wp_enqueue_style() and wp_enqueue_script(), something like these:

function admin_custom_css()
{ wp_enqueue_style( 'stylesheet_name', 'stylesheet.css') }; 

function admin_custom_js 
{ wp_enqueue_script( 'javascript_file', 'script.js') };

... and a few admin pages, created with add_menu_page() and add_submenu_page()

function my_menu() {
   add_menu_page('Page 1', 'bar', 'something', 'else', 'foo');
   add_submenu_page( 'theme_menu', 'Subpage 1', 'Subpage', 'something', 'else', 'foo'); 
}
add_action('admin_menu', 'my_menu'); 

How do I load my two functions only on these pages?

Right now I'm using:

add_action('admin_init', 'admin_custom_css' ); 
add_action('admin_init', 'admin_custom_js' );  

But it loads my files on every admin page, which is not nice at all.

Can I do this via one simple line in functions.php or have to enqueue them within my pages separately (I prefer the first option strongly, since I'd have to edit a lot of admin-page-creating-functions).

Thanks!

1

9 Answers 9

45

add_menu_page and add_submenu_page both return the page's "hook suffix", which can be used to identify the page with certain hooks. As such, you can use that suffix in combination with the variable hooks admin_print_styles-{$hook_suffix} and admin_print_scripts-{$hook_suffix} to specifically target these pages.

function my_menu() {
   $menu = add_menu_page( 'Page 1', 'bar', 'something', 'else', 'foo' );
   $submenu = add_submenu_page( 'theme_menu', 'Subpage 1', 'Subpage', 'something', 'else', 'foo' );

   add_action( 'admin_print_styles-' . $menu, 'admin_custom_css' );
   add_action( 'admin_print_styles-' . $submenu, 'admin_custom_css' );

   add_action( 'admin_print_scripts-' . $menu, 'admin_custom_js' );
   add_action( 'admin_print_scripts-' . $submenu, 'admin_custom_js' );
}

I find this to be a clean method for adding all of this because it's all handled within the one function. If you decide to remove this functionality, simply remove the call to the one function.

4
  • 10
    This answer is not technically correct. the Codex for admin_print_scripts() states "admin_print_scripts should not be used to enqueue styles or scripts." The answer by @TomAuger is actually the correct one, although not optimal. It would be beneficial if the WP team added an admin_enqueue_scripts-(hookname) hook though...
    – David Gard
    May 2, 2014 at 15:15
  • It took me 3 days to find this answer which was really helpful for me :) Thanks :) Nov 24, 2016 at 6:43
  • @DavidGard, you should probably look at these developer.wordpress.org/reference/hooks/… , developer.wordpress.org/reference/hooks/… Feb 24, 2018 at 18:34
  • 1
    @hkchakladar My comment is nearly four years old... If it's no longer relevant, by all means add a more up to date comment explaining why.
    – David Gard
    Feb 24, 2018 at 18:38
87

The problem with @tollmanz answer is that since you're hooking off of the -print-styles and -print-scripts hooks, you must generate the HTML to load your scripts manually. This is not optimal, since you don't get the nice dependency and versioning that comes with wp_enqueue_script() and wp_enqueue_style(). It also doesn't let you put things in the footer if that's a better place for them.

So, back to the OP's question: what's the best way to ensure that I can enqueue JS / CSS on specific admin pages only?

  1. Hook off the "load-{$my_admin_page}" action to only do things when it's your specific plugin's admin page that's loaded, and then

  2. Hook off the "admin_enqueue_scripts" action to properly add your wp_enqueue_script calls.

Seems like a bit of a pain, but it's actually very easy to implement. From the top:

    add_action( 'admin_menu', 'add_my_admin_menus' ); // hook so we can add menus to our admin left-hand menu

    /**
     * Create the administration menus in the left-hand nav and load the JavaScript conditionally only on that page
     */
    function add_my_admin_menus(){
        $my_page = add_menu_page( 'Page Title', 'Menu Title', MY_ADMIN_CAPABILITY, 'menu-slug', 'show_page_content' );

        // Load the JS conditionally
        add_action( 'load-' . $my_page, 'load_admin_js' );
    }

    // This function is only called when our plugin's page loads!
    function load_admin_js(){
        // Unfortunately we can't just enqueue our scripts here - it's too early. So register against the proper action hook to do it
        add_action( 'admin_enqueue_scripts', 'enqueue_admin_js' );
    }

    function enqueue_admin_js(){
        // Isn't it nice to use dependencies and the already registered core js files?
        wp_enqueue_script( 'my-script', INCLUDES_URI . '/js/my_script.js', array( 'jquery-ui-core', 'jquery-ui-tabs' ) );
    }
}
6
  • 6
    +1 - This is the way to go IMO. The individual namespaced (someaction-$hook) hooks are nice for 1 or 2 actions, but if you're authoring a plugin, you may need to do a lot of different things just on your option page(s) which makes this method really convenient. I usually just add 1 action to the load-$hook hook that fires my option_page_actions function to which I may add many other hooks/filters etc. Because those actions are only called on the page of choice, hooks beyond that point don't need to use the namespaced hooks (as you have shown), which is much more efficient & intuitive. Jun 2, 2013 at 16:34
  • Hi, is this way still supported? load_admin_js is never calling Mar 23, 2014 at 19:53
  • Sure it's still supported. Line 206 of admin.php. Been there since 2.6, and unlikely to go away any time soon (ever).
    – Tom Auger
    Mar 24, 2014 at 14:01
  • Looking at my answer now, I believe that explicitly enqueueing jquery-ui-core and jquery-ui-tabs is entirely superfulous, since those scripts are already registered. You just need to call them in the dependency. I'll update my answer accordingly.
    – Tom Auger
    Apr 26, 2015 at 1:17
  • Works perfectly with WordPress 4.9.6
    – ethmz
    Jun 18, 2018 at 1:45
16

If you use get_current_screen(), you can detect what the page you're on is. There is an example in the codex article that I linked which shows how to use get_current_screen() with add_options_page(), this method will work for any admin page.

0
5

I was wondering the same thing. There's a modern version that uses admin_enqueue_scripts:

add_action('admin_menu', function () {
  $settingsPage = add_options_page('Settings', 'Mortgage Calculator', 'manage_options', 'mortgagecalculator', function () {
    echo "<div id='app'></div>";
  });
  /**
   * Include the ember admin scripts only on pages where it's needed.
   */
  add_action("admin_enqueue_scripts", function ($hook) use ($settingsPage){
    if($hook !== $settingsPage){
      return;
    }
    // Remove default jQuery since Ember provides its own.
    wp_dequeue_script('jquery');
    wp_enqueue_script('ember-vendor', plugins_url("admin/assets/vendor.js", __FILE__));
    wp_enqueue_script('ember-project', plugins_url("admin/assets/mortgage-plugin-ember-admin.js", __FILE__), ['ember-vendor']);
    wp_enqueue_script('ember-live-reload', "http://localhost:4200/ember-cli-live-reload.js");
  });
});
5

As @mor7ifer mentioned above, you can use the native WordPress function get_current_screen(). If you loop through the output of this function, e.g.:

$current_screen = get_current_screen();
foreach($current_screen as $key => $value) {
    error_log(print_r($key,1));
}

... you'll notice a key called base. I use this detect what page I'm on and enqueue, dequeue like so:

add_action('admin_enqueue_scripts', 'some_hook_function')* ):

public function some_hook_function(){

    // # only register and queue scripts & styles on POST edit screen of admin
    $current_page = get_current_screen()->base;
    if($current_page == 'post' || $current_page == 'page') {

        wp_enqueue_script('datetimepicker', plugins_url('assets/jquery-ui-timepicker-addon.min.js', __FILE__), array('jquery', 'jquery-ui-datepicker', 'jquery-ui-slider'), '1.9.1', true);

        wp_enqueue_style( 'jquery-ui-datepicker', plugins_url('assets/jquery-ui.min.css', __FILE__), array(), '1.11.2', 'all');


    } else { // # if not on post page, deregister and dequeue styles & scripts

        wp_dequeue_script('datetimepicker');
        wp_dequeue_style('jquery-ui-datepicker');

    }
}
4

To make it, you have to find the admin page name first. Add admin_enqueue_scripts with wp_die($hook) and go to your specific plugin page, You will see the page name.

function my_plugin_scripts($hook) {
    wp_die($hook);
}
add_action( 'admin_enqueue_scripts', 'my_plugin_scripts' );

settings_page_plugging_info

Now copy the page name and use it in condition to load the scripts on the specific page.

function my_plugin_scripts($hook) {
    if ( 'settings_page_plugging_info' != $hook ) {
        return;
    }

    wp_enqueue_script( 'my_custom_script', plugins_url('js/file.js', __FILE__));
}
add_action( 'admin_enqueue_scripts', 'my_plugin_scripts' );
1
  • This is the correct approach. All the previous answers to this post are overly convoluted and/or plain wrong.
    – Miqi180
    Mar 4, 2022 at 0:06
3

You could take @tollmanz answer, and expand on it slightly, allowing for conditional usage as well...

Example:

/* Add admin pages */   
function my_admin_pages(){
    $menu = array();
    $menu['main_page'] = add_menu_page('Page 1', 'bar', 'something', 'else', 'foo');
    $menu['sub_page'] = add_submenu_page('theme_menu', 'Subpage 1', 'Subpage', 'something', 'else', 'foo');
    foreach($menu as $key => $value){
        if($key == 'main_page'){
            /* Print styles on only the main page. */
            add_action('admin_print_styles-'.$value, 'print_styles');
        }
        /* Print scripts on all of our admin pages. */
        add_action('admin_print_scripts-'.$value, 'print_scripts');
    }
}
add_action('admin_menu', 'my_admin_pages');
0

From the documentation:

admin_print_scripts mainly used to echo inline javascript. admin_print_scripts should not be used to enqueue styles or scripts on the admin pages. Use admin_enqueue_scripts instead."

Same with admin_print_styles.

1
0
add_action( 'admin_menu', 'add_my_admin_menus' ); 

function add_my_admin_menus() {
    $GLOBALS['my_page'] = add_menu_page( 'Page Title', 'Menu Title', MY_ADMIN_CAPABILITY, 'menu-slug', 'show_page_content');
    add_action( 'admin_enqueue_scripts', 'enqueue_admin_js');
}

function enqueue_admin_js($hook) {
    if($GLOBALS['my_page'] === $hook) {
        wp_enqueue_script( 'jquery-ui-core' );
        wp_enqueue_script( 'jquery-ui-tabs' );
        // Isn't it nice to use dependencies and the already registered core js files?
        wp_enqueue_script( 'my-script', INCLUDES_URI . '/js/my_script.js', array( 'jquery-ui-core', 'jquery-ui-tabs' ) );
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.