Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Repeating Custom Fields in a Metabox
<?
/**
* Repeatable Custom Fields in a Metabox
* Author: Helen Hou-Sandi
*
* From a bespoke system, so currently not modular - will fix soon
* Note that this particular metadata is saved as one multidimensional array (serialized)
*/
function hhs_get_sample_options() {
$options = array (
'Option 1' => 'option1',
'Option 2' => 'option2',
'Option 3' => 'option3',
'Option 4' => 'option4',
);
return $options;
}
add_action('admin_init', 'hhs_add_meta_boxes', 1);
function hhs_add_meta_boxes() {
add_meta_box( 'repeatable-fields', 'Repeatable Fields', 'hhs_repeatable_meta_box_display', 'post', 'normal', 'default');
}
function hhs_repeatable_meta_box_display() {
global $post;
$repeatable_fields = get_post_meta($post->ID, 'repeatable_fields', true);
$options = hhs_get_sample_options();
wp_nonce_field( 'hhs_repeatable_meta_box_nonce', 'hhs_repeatable_meta_box_nonce' );
?>
<script type="text/javascript">
jQuery(document).ready(function( $ ){
$( '#add-row' ).on('click', function() {
var row = $( '.empty-row.screen-reader-text' ).clone(true);
row.removeClass( 'empty-row screen-reader-text' );
row.insertBefore( '#repeatable-fieldset-one tbody>tr:last' );
return false;
});
$( '.remove-row' ).on('click', function() {
$(this).parents('tr').remove();
return false;
});
});
</script>
<table id="repeatable-fieldset-one" width="100%">
<thead>
<tr>
<th width="40%">Name</th>
<th width="12%">Select</th>
<th width="40%">URL</th>
<th width="8%"></th>
</tr>
</thead>
<tbody>
<?php
if ( $repeatable_fields ) :
foreach ( $repeatable_fields as $field ) {
?>
<tr>
<td><input type="text" class="widefat" name="name[]" value="<?php if($field['name'] != '') echo esc_attr( $field['name'] ); ?>" /></td>
<td>
<select name="select[]">
<?php foreach ( $options as $label => $value ) : ?>
<option value="<?php echo $value; ?>"<?php selected( $field['select'], $value ); ?>><?php echo $label; ?></option>
<?php endforeach; ?>
</select>
</td>
<td><input type="text" class="widefat" name="url[]" value="<?php if ($field['url'] != '') echo esc_attr( $field['url'] ); else echo 'http://'; ?>" /></td>
<td><a class="button remove-row" href="#">Remove</a></td>
</tr>
<?php
}
else :
// show a blank one
?>
<tr>
<td><input type="text" class="widefat" name="name[]" /></td>
<td>
<select name="select[]">
<?php foreach ( $options as $label => $value ) : ?>
<option value="<?php echo $value; ?>"><?php echo $label; ?></option>
<?php endforeach; ?>
</select>
</td>
<td><input type="text" class="widefat" name="url[]" value="http://" /></td>
<td><a class="button remove-row" href="#">Remove</a></td>
</tr>
<?php endif; ?>
<!-- empty hidden one for jQuery -->
<tr class="empty-row screen-reader-text">
<td><input type="text" class="widefat" name="name[]" /></td>
<td>
<select name="select[]">
<?php foreach ( $options as $label => $value ) : ?>
<option value="<?php echo $value; ?>"><?php echo $label; ?></option>
<?php endforeach; ?>
</select>
</td>
<td><input type="text" class="widefat" name="url[]" value="http://" /></td>
<td><a class="button remove-row" href="#">Remove</a></td>
</tr>
</tbody>
</table>
<p><a id="add-row" class="button" href="#">Add another</a></p>
<?php
}
add_action('save_post', 'hhs_repeatable_meta_box_save');
function hhs_repeatable_meta_box_save($post_id) {
if ( ! isset( $_POST['hhs_repeatable_meta_box_nonce'] ) ||
! wp_verify_nonce( $_POST['hhs_repeatable_meta_box_nonce'], 'hhs_repeatable_meta_box_nonce' ) )
return;
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
return;
if (!current_user_can('edit_post', $post_id))
return;
$old = get_post_meta($post_id, 'repeatable_fields', true);
$new = array();
$options = hhs_get_sample_options();
$names = $_POST['name'];
$selects = $_POST['select'];
$urls = $_POST['url'];
$count = count( $names );
for ( $i = 0; $i < $count; $i++ ) {
if ( $names[$i] != '' ) :
$new[$i]['name'] = stripslashes( strip_tags( $names[$i] ) );
if ( in_array( $selects[$i], $options ) )
$new[$i]['select'] = $selects[$i];
else
$new[$i]['select'] = '';
if ( $urls[$i] == 'http://' )
$new[$i]['url'] = '';
else
$new[$i]['url'] = stripslashes( $urls[$i] ); // and however you want to sanitize
endif;
}
if ( !empty( $new ) && $new != $old )
update_post_meta( $post_id, 'repeatable_fields', $new );
elseif ( empty($new) && $old )
delete_post_meta( $post_id, 'repeatable_fields', $old );
}
?>
  • stripslashes() your $_POST values.
  • esc_attr() for anything that echoes in an HTML attribute. Especially on line 72!
Owner

helen commented Jan 11, 2012

Yes, sir.

thanks for the code i was wondering, how can i add another custom fields so that i can save video and audio in two different custom fields

oterox commented Jan 24, 2013

it would be possible to make the rows sortable?

oterox commented Jan 24, 2013

forget it, i've done it :)

How to use radio buttons instead of select box ?

Where I need to put the code? in functions.php?

deemi commented Apr 18, 2014

Thanx alot its very helpful to me - just edit some code. :)

reypm commented Jun 6, 2014

@helenhousandi how I use this approach in a plugin? I tried as this post show and can't get it to work, could any of the experts here give me some help?

majadc commented Jun 25, 2014

Hi, it's so great. I have a question. Do you know to implement group of input type checkbox to this solution? I want to want to be able to save more than one value for the same field. I appreciate any help. Thank you.

I like the results I see in the single.php file

Hi,
Could you help me how can I unserialize the result?
I made my own filed and this is the result:
a:1:{i:0;a:1:{s:7:"address";s:6:"Russia";}}

Thanks,

Try to use function get_post_meta( $post_id, $key) http://codex.wordpress.org/Function_Reference/get_post_meta

hey i am writing all of the above code but there is no any response means there is no any meta box is created

What should I use in my template in order to display a certain field value in my webpage?

Awesome! Thanks for sharing this. It is very similar to what I needed. One of my repeating inputs, is repeating.

how can i add repeatable fields in my code

__('Music Albums'), 'singular_label' => __('Music Album'), 'public' => true, 'show_ui' => true, 'capability_type' => 'post', 'hierarchical' => true, 'has_archive' => true, 'supports' => array('title', '', 'thumbnail'), 'rewrite' => array('slug' => 'musicalbums', 'with_front' => false), ); //Register type and custom taxonomy for type. register_post_type( 'musicalbums' , $args ); register_taxonomy("business-type", array("musicalbums"), array("hierarchical" => true, "label" => "Album Types", "singular_label" => "Album Type", "rewrite" => true, "slug" => 'album-type')); add_action("admin_init", "music_albums_add_meta"); function music_albums_add_meta(){ add_meta_box("musicalbum-meta", "Tracks", "Music_albums_meta_options", "musicalbums", "normal", "high"); } function Music_albums_meta_options(){ global $post; if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return $post_id; $custom = get_post_custom($post->ID); $upload_track = $custom["upload_track"][0]; $tracktitle = $custom["tracktitle"][0]; $artist= $custom["artist"][0]; $imageurl = $custom["imageurl"][0]; $iconurl = $custom["iconurl"][0]; $downloadText = $custom["downloadText"][0]; $ExtraInfoText = $custom["ExtraInfoText"][0]; ?>
Upload MP3 :
ID ); //require_once('getid3/getid3.php'); $prefix = 'sample_'; $fields = array( array( // Text Input 'label' => 'Text Input', // 'desc' => 'A description for the field.', // description 'id' => $prefix.'text', // field id and name 'type' => 'text' // type of field ), array( // Textarea 'label' => 'Textarea', // 'desc' => 'A description for the field.', // description 'id' => $prefix.'textarea', // field id and name 'type' => 'textarea' // type of field ) ); ?>
Track Title :
Artist :
Icon Url:
Download Link :
Extra Info Text:

Add Another

add_action('save_post', 'business_manager_save_extras');
function business_manager_save_extras(){
global $post;
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ){
//if you remove this the sky will fall on your head.
return $post_id;
}else{
update_post_meta($post->ID, "iconurl",
$_POST["iconurl"]);
update_post_meta($post->ID, "tracktitle", $_POST["tracktitle"]);
update_post_meta($post->ID, "artist", $_POST["artist"]);
update_post_meta($post->ID, "upload_track",
$_POST["upload_track"]);
update_post_meta($post->ID, "upload_track_two",
$_POST["upload_track_two"]);
update_post_meta($post->ID, "imageurl", $_POST["imageurl"]);
update_post_meta($post->ID, "downloadText", $_POST["downloadText"]);
update_post_meta($post->ID, "ExtraInfoText", $_POST["ExtraInfoText"]);
}
}

add_filter("manage_edit-musicalbums_columns", "business_manager_edit_columns");
function business_manager_edit_columns($columns){
$columns = array(
"cb" => "<input type="checkbox" />",
"title" => "Albums Name",
"upload_track" => "Track",
"ExtraInfoText" => "Extra Info Text",
"cat" => "Category",
);
return $columns;
}

add_action("manage_musicalbums_posts_custom_column",
"business_manager_custom_columns");
function business_manager_custom_columns($column){
global $post;
$custom = get_post_custom();
switch ($column)
{

case "upload_track":
$upload_track= $custom["upload_track"][0].'
';
echo $upload_track;
break;
case "ExtraInfoText":
echo $custom["ExtraInfoText"][0];
break;
case "cat":
echo get_the_term_list($post->ID, 'business-type');
break;
}
}

}
?>

Display in single Post

PHP code

<?php $repeatable_fields = get_post_meta($post->ID, 'repeatable_fields', true);  if ( $repeatable_fields ) : ?>
    <div class="list">
        <?php foreach ( $repeatable_fields as $field ) { ?>
        <div class="row">
            <?php if($field['name'] != '') echo '<span class="field">'. esc_attr( $field['name'] ) . '</span>'; ?>
            <?php if($field['select'] != '') echo '<span class="field">'. esc_attr( $field['select'] ) . '</span>'; ?>
            <?php if($field['url'] != '') echo '<span class="field">'. esc_attr( $field['url'] ) . '</span>'; ?>
        </div>
        <?php } ?> 
    </div>
<?php endif; ?>

CSS Code

.list {
    float: left;
    width: 100%;
    padding: 15px;
}
.list .row {
    width: 100%;
    padding: 5px 0;
    float: left;
}
.list .row span.field {
    width: calc(100% / 3);
    float: left;
}

hi @mundothemes, You could share your code, because the one you show is almost exactly what I want, ie a button to upload images, add a URL and just as the field is repeatable.

biklik commented Apr 1, 2017

Hi Helen! very nice work!
One question...is there any way to implement that code in a WordPress options page with settings API? I can build the form but the problema is to sanitize and save data.

Thank you!! +1

scygeek commented Apr 17, 2017

Is there a way to create a dynamic ID to each name input when create based like

it have problem :
Parse error: syntax error, unexpected '}' on line 119

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment