I am working on a meta box for events. Each event has it's own page with a meta box for the line-up, background image, tickets page URL and some text.

To create the line-up I would like to use the repeatable fields from the "Reusable Custom Meta Boxes tutorial" from WP Tuts +: http://wp.tutsplus.com/tutorials/reusable-custom-meta-boxes-part-1-intro-and-basic-fields/.

However, I don't know how to add multiple fields within the repeatable fields. This is the idea:

- Text field: Name of the artist
- Text field: Artist website
- Checkbox: Headliner (Yes or no)

This is the code from the tutorial:

function meta_box_callback($fields, $page) {
    global $post;
    echo '<input type="hidden" name="'.$page.'_meta_box_nonce" value="'.wp_create_nonce(basename(__FILE__)).'" />';

    // Begin the field table and loop
    echo '<table class="form-table cpt">';
    foreach ($fields as $field) {
        // get value of this field if it exists for this post
        if ($field['label'])    $label      = $field['label'];
        if ($field['desc'])     $desc       = '<span class="description">'.$field['desc'].'</span>';
        if ($field['id'])       $id         = $field['id'];
        if ($field['type'])     $type       = $field['type'];
        if ($field['value'])    $value      = $field['value'];
        if ($field['options'])  $options    = $field['options'];

        $meta   = get_post_meta($post->ID, $id, true);
        // begin a table row with
        echo '<tr>
                <th class="cpt_title"><label for="'.$id.'">'.$label.'</label></th>
                <td class="cpt_content">';
                switch($field['type']) {
                    case 'repeatable':
                        echo '<a class="repeatable-add button" href="#">+</a>
                                <ul id="'.$field['id'].'-repeatable" class="custom_repeatable">';
                        $i = 0;
                        if ($meta) {
                            foreach($meta as $row) {
                                echo '<li><span class="sort hndle">|||</span>
                                            <input type="text" name="'.$field['id'].'['.$i.']" id="'.$field['id'].'" value="'.$row.'" size="30" />
                                            <a class="repeatable-remove button" href="#">-</a></li>';
                        } else {
                            echo '<li><span class="sort hndle">|||</span>
                                        <input type="text" name="'.$field['id'].'['.$i.']" id="'.$field['id'].'" value="" size="30" />
                                        <a class="repeatable-remove button" href="#">-</a></li>';
                        echo '</ul>
                            <span class="description">'.$field['desc'].'</span>';
                } // switch
        echo '</td></tr>';
    } // foreach
    echo '</table>'; // table
function meta_box_save($post_id, $fields, $page) {

    // verify nonce
    if (!wp_verify_nonce($_POST[$page.'_meta_box_nonce'], basename(__FILE__))) 
        return $post_id;
    // check autosave
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
        return $post_id;
    // check permissions
    if ($page != $_POST['post_type']) {
        if (!current_user_can('edit_page', $post_id))
            return $post_id;
        } elseif (!current_user_can('edit_post', $post_id)) {
            return $post_id;

    // loop through fields and save the data
    foreach ($fields as $field) {
        if($field['type'] == 'tax_select') {
            // save taxonomies
            $term = $_POST[$field['id']];
            wp_set_object_terms( $post_id, $term, $field['id'] );
        else {
            // save the rest
            $old = get_post_meta($post_id, $field['id'], true);
            $new = $_POST[$field['id']];
            if ($new && $new != $old) {
                update_post_meta($post_id, $field['id'], $new);
            } elseif ('' == $new && $old) {
                delete_post_meta($post_id, $field['id'], $old);
    } // foreach

Hope you guys can help me out :-).


Try Fieldmanager. It was built with repeating groups being priority #1. Your new code would look something like this:

add_action( 'init', function() {
    $fm = new Fieldmanager_Group( array(
        'name'           => 'artists',
        'limit'          => 0,
        'label'          => 'New Artist',
        'label_macro'    => array( 'Artist: %s', 'name' ),
        'add_more_label' => 'Add another Artist',
        'children'       => array(
            'name'      => new Fieldmanager_Textfield( 'Name' ),
            'website'   => new Fieldmanager_Link( 'Website' ),
            'headliner' => new Fieldmanager_Checkbox( 'Headliner' )
        ) );
    $fm->add_meta_box( 'Artists', array( 'post' ) );
} );

Disclosure: The company I work for open-sources this plugin.

protected by Community Jan 4 '13 at 20:35

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.