Custom Metabox Per Template

so this came about when i was tasked to create a custom metabox for a wordpress site at work. i didn’t want the metabox to appear unless a specific template was chosen — this is so as not to confuse the person in the admin with new options they shouldn’t be messing with.

i found this solution, but it wasn’t quite working in my admin. so i put on my wordpress/php developer cap and dissected it down to the following:

functions.php

function custom_metabox_per_template() {
    global $pagenow,$typenow;
    if ( is_admin() && in_array( $pagenow, array( 'post.php', 'post-new.php' ) ) && $typenow == 'page') { ?>
      <script type='text/javascript'>
        jQuery(document).ready(function($) {
          //hide all metaboxs
          function hide_all_custom_metaboxes(){
            $('#template1').hide();
            $('#template2').hide();
            $('#template3').hide();
          }
          //show a metabox
          function show_custom_metabox(meta_id){
            var selector = "#"+meta_id;
            if( $(selector).length)
              $(selector).show();
          }
          //first hide all metaboxes
          hide_all_custom_metaboxes();
          //then check for selected page template and show the corect metabox
          var current_metabox = $('#page_template').val();
          var split = current_metabox.split(".php");
          var split_name = split[0];
          show_custom_metabox(split_name);

          //and last listen for changes update when needed
          $('#page_template').bind("change", function(){
            hide_all_custom_metaboxes();
            //show_custom_metabox($('#page_template').val());
            var current_metabox = $('#page_template').val();
            var split = current_metabox.split(".php");
            var split_name = split[0];
            show_custom_metabox(split_name);
         });
        });
      </script>
    < ?php }
}
add_action('admin_footer', 'custom_metabox_per_template');
?>

explanation

$('#template1').hide();
$('#template2').hide();
$('#template3').hide();

this code finds those metaboxes with the specified ID’s and hides them with jQuery

essentially, you’ll change the ID’s to whatever your template php filename is.

var current_metabox = $('#page_template').val();
var split = current_metabox.split(".php");
var split_name = split[0];
show_custom_metabox(split_name);

this is where i had to make a modification to that guy’s code. for that template dropdown, the values are the template filenames:

page template dropdown

<select id="page_template" name="page_template">
  <option value="template1.php">Template 1</option>
  <option value="template2.php">Template 2</option>
  <option value="template3.php">Template 3</option>
</select>

since we’re using the value to hide the ID, this causes an issue — ID’s can’t have periods in them. therefore, i put a split for that variable on the “.php” part to get just the filename without extension. BINGO!

now you can have a metabox appear based on a chosen template

refresher: custom meta boxes

i wrote this assuming you knew how to write a custom meta box… if you don’t, look it up. though this is the add function:

add_action( 'add_meta_boxes', 'template1_add_post_meta_boxes' );
add_action( 'save_post', 'template1_post_class_meta_box', 10, 2 );

function template1_add_post_meta_boxes() {
  add_meta_box(
    'template1',      // Unique ID -- this will match what the filename is
    esc_html__( 'Template 1 Meta Box', 'example' ),    // Title
    'template1_post_class_meta_box',   // Callback function
    'page',         // Admin page (or post type)
    'normal',         // Context
    'default'         // Priority
  );
}
function template1_post_class_meta_box( $object, $box ) {
  ...
}

Leave a Reply