WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'd like users to be able to create and remove additional meta box fields as needed.

For example, say a music podcast with a variable amount of songs played per episode. The user should be able to click a button that will add additional fields to enter each song as needed.

Ideally this would be done without the use of a plugin, but coded into the functions file.

share|improve this question
you are describing the built in custom fields metabox! – Bainternet Jun 12 '11 at 23:42
I guess essentially that's how it works, but it is only set up to do one field at a time, and it's not very end user friendly. – Picard102 Jun 13 '11 at 0:11
up vote 46 down vote accepted

So you mean something like this?

enter image description here

and when you click on Add tracks it becomes this:

enter image description here

if it is what you mean the its done by creating a metabox that has simple jquery function to add and remove fields in it, and the data is saved as an array in of data in a single meta row, here you go:

add_action( 'add_meta_boxes', 'dynamic_add_custom_box' );

/* Do something with the data entered */
add_action( 'save_post', 'dynamic_save_postdata' );

/* Adds a box to the main column on the Post and Page edit screens */
function dynamic_add_custom_box() {
        __( 'My Tracks', 'myplugin_textdomain' ),

/* Prints the box content */
function dynamic_inner_custom_box() {
    global $post;
    // Use nonce for verification
    wp_nonce_field( plugin_basename( __FILE__ ), 'dynamicMeta_noncename' );
    <div id="meta_inner">

    //get the saved meta as an arry
    $songs = get_post_meta($post->ID,'songs',true);

    $c = 0;
    if ( count( $songs ) > 0 ) {
        foreach( $songs as $track ) {
            if ( isset( $track['title'] ) || isset( $track['track'] ) ) {
                printf( '<p>Song Title <input type="text" name="songs[%1$s][title]" value="%2$s" /> -- Track number : <input type="text" name="songs[%1$s][track]" value="%3$s" /><span class="remove">%4$s</span></p>', $c, $track['title'], $track['track'], __( 'Remove Track' ) );
                $c = $c +1;

<span id="here"></span>
<span class="add"><?php _e('Add Tracks'); ?></span>
    var $ =jQuery.noConflict();
    $(document).ready(function() {
        var count = <?php echo $c; ?>;
        $(".add").click(function() {
            count = count + 1;

            $('#here').append('<p> Song Title <input type="text" name="songs['+count+'][title]" value="" /> -- Track number : <input type="text" name="songs['+count+'][track]" value="" /><span class="remove">Remove Track</span></p>' );
            return false;
        $(".remove").live('click', function() {


/* When the post is saved, saves our custom data */
function dynamic_save_postdata( $post_id ) {
    // verify if this is an auto save routine. 
    // If it is our form has not been submitted, so we dont want to do anything
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) 

    // verify this came from the our screen and with proper authorization,
    // because save_post can be triggered at other times
    if ( !isset( $_POST['dynamicMeta_noncename'] ) )

    if ( !wp_verify_nonce( $_POST['dynamicMeta_noncename'], plugin_basename( __FILE__ ) ) )

    // OK, we're authenticated: we need to find and save the data

    $songs = $_POST['songs'];

share|improve this answer
It seems to only display "array(0) { } Add Tracks" when I use the above code. – Picard102 Jun 14 '11 at 2:06
Yeah just remove var_dump($songs); – Bainternet Jun 14 '11 at 7:44
Cool, that fixed that, but now the data doesn't seem to be saving on update. Or at least it's not showing the data as fields under My Track, nor in Custom Fields. If I put the var_dump back in though it spits out "array(1) { [0]=> array(1) { [1]=> array(2) { ["title"]=> string(4) "test" ["track"]=> string(5) "teste" } } } Add Tracks" – Picard102 Jun 15 '11 at 6:16
Not really sure whats the problem, its not an exact code, its an example and its working fine on my end, try changing if (count($songs) > 0){ to if(is_array($songs)){ – Bainternet Jun 27 '11 at 8:01

This is done through custom fields BUT you should never use anything that lets users add create or remove meta boxes. These write directly into the database so you could potentially create a whole lot of problems for your site if you give users this kind of control. It's far safer for you to create the maximum number of custom fields they may need and let them leave some blank where they are not needed.

This is also plugin territory. The functions file is theme-specific whereas plugins are for functions that apply to the site content, especially if you want that content to be available regardless of which theme you use.

Some suggestions:



share|improve this answer
BUT you should never use anything that lets users add or remove meta boxes Why? – tnorthcutt Jun 13 '11 at 12:34
My only concern is that with any plugin comes the chance that it might stop being supported in the future. I feel that it's probably more likely that I'd be able to figure out how to fix a simple addition to the functions file, than figure out how to fix a plugin. – Picard102 Jun 14 '11 at 2:08
Plugins are essentially functions that reside outside of the theme. You can take a plugin and copy the code into functions.php and it will work. Similarly, you can take functions out of functions.php, add the necessary header for the plugin, and it works just the same as soon as you activate it. – Elpie Jun 14 '11 at 2:14
Good to know. I tried the two plugins you suggested, but neither of them let me really do what I needed that I couldn't already do without the plugin. Thanks for the suggestions though. – Picard102 Jun 14 '11 at 2:26

protected by toscho Mar 18 at 10:20

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

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