I am trying to create a custom meta box where the user can add fields as needed. I followed this tutorial:
http://wp.tutsplus.com/tutorials/reusable-custom-meta-boxes-part-1-intro-and-basic-fields/
I would like to expand on this tutorial and create a repeatable field that allows two inputs. For Example: Name and URL.
How could I achieve this?
I found this other question here: Create more Meta Boxes as needed
I was able to integrate the meta box example into my custom post type but I couldn’t figure out how to output the meta values into my theme. Here the code I am working with:
/*---------------------------*/
/* Define Metabox Fields
/*---------------------------*/
$prefix = 'tz_';
$custom_downloads = array(
'id' => 'custom-downloads',
'title' => __('Custom Downloads Downloads (Beta)'),
'page' => 'categories-supported',
'context' => 'normal',
'priority' => 'high',
'fields' => array(
array(
'name' => __('Add Product Downloads', 'framework'),
'desc' => __('This meta box is under development', 'framework'),
'id' => $prefix . 'custom-downloads',
'type' => 'text',
'std' => ''
),
)
);
/*-------------------------------------*/
/* Add Meta Box to CPT screen
/*-------------------------------------*/
function tz_add_box() {
global $custom_downloads;
add_meta_box($custom_downloads['id'], $custom_downloads['title'], 'tz_show_box_custom_dwnld', $custom_downloads['page'], $custom_downloads['context'], $custom_downloads['priority']);
}
}
add_action('admin_menu', 'tz_add_box');
/*------------------------------------------*/
/* Callback function/show fields in meta box
This is taken directly from: https://wordpress.stackexchange.com/questions/19838/create-more-meta-boxes-as-needed
/*------------------------------------------*/
function tz_show_box_custom_dwnld() {
global $custom_downloads, $post;
// Use nonce for verification
echo '<input type="hidden" name="tz_meta_box_nonce" value="', wp_create_nonce(basename(__FILE__)), '" />';
?>
<div id="meta_inner">
<?php
//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>
<script>
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() {
$(this).parent().remove();
});
});
</script>
</div>
<?php
}
/*-------------------------------------*/
/* Save data when post is edited
/*-------------------------------------*/
function tz_save_data($post_id) {
global $meta_box, $meta_box_video, $meta_box_video_page, $meta_box_product_tabs, $meta_deployments, $meta_features, $meta_downloads;
// verify nonce
if (!wp_verify_nonce($_POST['tz_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;
}
$songs = $_POST['songs'];
update_post_meta($post_id,'songs',$songs);
}
add_action('save_post', 'tz_save_data');
Using The above code I am able to generate the dynamic meta box on my CPT edit screen and am able to save data in the fields successfully.
I’m a little embarrassed to admit it, but I don’t know how to display the info from these fields in my theme. I have been able to successfully display other custom meta information stored in other fields by using
<?php $post_meta_data = get_post_custom($post->ID); ?>
<?php $custom_features = unserialize($post_meta_data['tz_features-repeat'][0]); ?>
<?php echo '<ul class="deployments">';
foreach ($custom_deployments as $string) {
echo '<li>'.$string.'</li>';
}
echo '</ul>';
?>
Any help would be greatly appreciated!
The serialized array your meta boxes are saving is deformed. I made a few slight changes to your code to get it to work. I created a new post and here is what was saved after being unserialized.
Note: WordPress will automatically unserialize an an array stored in post_meta. Use an online unserializer if you ever want to check the contents.
To output this on the front end you just call get_post_meta() and loop through the array.
On the front end this gives us a nice unordered list with the track and title:
Code Changes:
I had to change your page field to
post
in you meta box definitions to get it to load on a post and I also moved them inside the add_meta_box function so we wouldn’t have to deal with making them global. In your show box function I cast the get_post_meta variable to an array to get rid of the invalid argument supplied for foreach error I got in Xdebug and fixed your counter.