Reusable Custom Meta Boxes Part 3: Extra Fields

Reusable Custom Meta Boxes Part 3: Extra Fields

Tutorial Details
  • Program: WordPress
  • Difficulty: Moderate
  • Estimated Completion Time: 10-15 Minutes
This entry is part 3 of 4 in the series Reusable Custom Meta Boxes

In Part 1 and Part 2 of our custom meta box template tutorial series, we learned how to create a field array to loop through and create a custom meta box with your standard fields. Now let’s throw in a bit of JavaScript for some fancy, but highly useful fields.


Date Picker

Each of the fields we’re covering in this tutorial will require jQuery and the jQuery UI. Thankfully, WordPress makes it super easy to use these with wp_enqueue_script, and as of 3.3, all of the jQuery UI interactions and widgets are bundled with WordPress.

Since we’re working on a page that already enqueues jQuery, we can skip that, but we will need to get the jQuery UI Datepicker. We’ll also need to create our own stylesheet since the necessary CSS doesn’t come bundled in WordPress yet—although, they are working that out.

if(is_admin()) {
	wp_enqueue_script('jquery-ui-datepicker');
	wp_enqueue_style('jquery-ui-custom', get_template_directory_uri().'/css/jquery-ui-custom.css');
}

We only need to load these in the admin, and not on the front end of the site, so wrap the functions in a conditional. The first function calls the datepicker and will also load the jQuery UI Core. The second function will call our jquery-ui-custom.css stylesheet from the theme’s css folder. The example stylesheet included in the download at the beginning of this tutorial doesn’t require images. You can also create your own jQuery UI theme.

Now let’s look at the array item we need to add to our $custom_meta_fields array we started in Part 1.

array(
	'label'	=> 'Date',
	'desc'	=> 'A description for the field.',
	'id'	=> $prefix.'date',
	'type'	=> 'date'
)

This array is almost identical to our text item. It has a main label, a description, a unique id, and the date type is defined. We’re just going to go with a basic implementation of the date picker in our example here, but if you need to spice up your usage of the date picker, you could also add other information to the array such as the preferred format, localization, and date range to name a few. Then you could use that information in the following script caller we need to add to the head of the page:

add_action('admin_head','add_custom_scripts');
function add_custom_scripts() {
	global $custom_meta_fields, $post;
	
	$output = '<script type="text/javascript">
				jQuery(function() {';
				
	foreach ($custom_meta_fields as $field) { // loop through the fields looking for certain types
		if($field['type'] == 'date')
			$output .= 'jQuery(".datepicker").datepicker();';
	}
	
	$output .= '});
		</script&gt';
		
	echo $output;
}

This bit needs to be added outside of the $custom_meta_fields array and outside of the show_custom_meta_box callback function to initialize the date picker on all fields with the class of "datepicker".

// date
case 'date':
	echo '<input type="text" class="datepicker" name="'.$field['id'].'" id="'.$field['id'].'" value="'.$meta.'" size="30" />
			<br /><span class="description">'.$field['desc'].'</span>';
break;

This code will be added after the last “break;” in our meta box switch.

  • A basic text input
  • Add the class "datepicker" for the jQuery function to find
  • Optionally change the type to "date" to be HTML5 ready

Slider

Sometimes you need to collect a number that is set at an exact range or needs to be multiples of 5. The jQuery UI slider is great for this because it makes it easy to drag and slide to the number that you want to enter.

wp_enqueue_script('jquery-ui-slider');

Make sure to call the js file by adding this to your is_admin() wrapped enqueues.

array(
	'label'	=> 'Slider',
	'desc'	=> 'A description for the field.',
	'id'	=> $prefix.'slider',
	'type'	=> 'slider',
	'min'	=> '0',
	'max'	=> '100',
	'step'	=> '5'
)

Again, we’re adding this to our $custom_meta_fields array and there are a few special additions.

  • ‘min’ will be sued to set the minimum number allowed.
  • ‘max’ is for the maximum number allowed
  • ‘step’ is for setting what step interval to use.
if ($field['type'] == 'slider') {
	$value = get_post_meta($post->ID, $field['id'], true);
	if ($value == '') $value = $field['min'];
	$output .= '
			jQuery( "#'.$field['id'].'-slider" ).slider({
				value: '.$value.',
				min: '.$field['min'].',
				max: '.$field['max'].',
				step: '.$field['step'].',
				slide: function( event, ui ) {
					jQuery( "#'.$field['id'].'" ).val( ui.value );
				}
			});';
}

Add this bit of code to the loop in the add_custom_scripts function we created in the last field type. This will add the custom jQuery we need for setting up the slider.

  • Get the value saved in the post meta
  • If the value is empty (because it’s a new post), set the value to the minimum
  • Add the jQuery code to the output of the function using the values we set in the array.
  • The last bit will tell the value set by the slider to be saved in the input field
// slider
case 'slider':
$value = $meta != '' ? $meta : '0';
	echo '<div id="'.$field['id'].'-slider"></div>
			<input type="text" name="'.$field['id'].'" id="'.$field['id'].'" value="'.$value.'" size="5" />
			<br /><span class="description">'.$field['desc'].'</span>';
break;

Again, we’re just using a text field to receive the slider’s value.

  • Include a div with the same id set int he jQuery for the slider to be created with
  • The input could be set to hidden if you customize your slider to display the number differently.

Image

Since the introduction of Post Thumbnails, setting an image with a custom meta field isn’t something we do a lot, but every once in awhile there comes a time when you need to set an image other than the post thumbnail, especially when building a plugin that takes into account that the user’s theme might not support post thumbnails.

This field will add the ability to upload an image or select one from the media upload, display a preview of the image, and save the ID for maximum usage options.

Upload Button JavaScript

To get our button to trigger the media uploader, we’ll need to tie into it with a bit of javascript.

jQuery(function(jQuery) {
	
	jQuery('.custom_upload_image_button').click(function() {
		formfield = jQuery(this).siblings('.custom_upload_image');
		preview = jQuery(this).siblings('.custom_preview_image');
		tb_show('', 'media-upload.php?type=image&TB_iframe=true');
		window.send_to_editor = function(html) {
			imgurl = jQuery('img',html).attr('src');
			classes = jQuery('img', html).attr('class');
			id = classes.replace(/(.*?)wp-image-/, '');
			formfield.val(id);
			preview.attr('src', imgurl);
			tb_remove();
		}
		return false;
	});
	
	jQuery('.custom_clear_image_button').click(function() {
		var defaultImage = jQuery(this).parent().siblings('.custom_default_image').text();
		jQuery(this).parent().siblings('.custom_upload_image').val('');
		jQuery(this).parent().siblings('.custom_preview_image').attr('src', defaultImage);
		return false;
	});

});

Put these in a custom js file and enqueue it within your is_admin() wrapped enqueues.

wp_enqueue_script('custom-js', get_template_directory_uri().'/js/custom-js.js');

The first function finds the button we’re going to create soon with the class of "custom_upload_image_button’" and preforms a few different things on click.

  • Find the field where we’ll be saving the data and set it as "formfield"
  • Find the default image that will display the image preview and set it as "preview"
  • Tell thickbox to open the media uploader where you’ll select your image with an upload or from the media uploader
  • Collect the image’s url and set it as "imgurl"
  • Get the image’s id by stripping it from the image’s class and set it as "id"
  • Send the "id" to the value of "formfield"
  • Send the "imgurl" to the src of "preview"
  • Close the thickbox

The second function tells the link we’ll class as "custom_clear_image_button" to clear both the value of the form field and reset the preview to our default image.

Create the Field

array(
	'name'	=> 'Image',
	'desc'	=> 'A description for the field.',
	'id'	=> $prefix.'image',
	'type'	=> 'image'
)

We just need the basic information for this field.

// image
case 'image':
	$image = get_template_directory_uri().'/images/image.png';	
	echo '<span class="custom_default_image" style="display:none">'.$image.'</span>';
	if ($meta) { $image = wp_get_attachment_image_src($meta, 'medium');	$image = $image[0]; }				
	echo	'<input name="'.$field['id'].'" type="hidden" class="custom_upload_image" value="'.$meta.'" />
				<img src="'.$image.'" class="custom_preview_image" alt="" /><br />
					<input class="custom_upload_image_button button" type="button" value="Choose Image" />
					<small> <a href="#" class="custom_clear_image_button">Remove Image</a></small>
					<br clear="all" /><span class="description">'.$field['desc'].'';
break;

We have a few things going on here, but with the way we’ve written the javascript, this should work pretty well no matter how many image fields you add.

  • Set the path for the default image and save it in a hidden span to use with the remove link
  • If there’s already a saved image, ovveride it with the medium size of the saved image
  • Add a hidden field to save the image ID
  • Add the preview image
  • Add the Upload button and the Remove link

Repeatable Fields

When you really get into using custom meta fields to store various types of data for a post, you’ll eventually run into the need of having multiple instances of the same field. Using a bit of javascript, you can easily duplicate a field as many times as you need it, and even sort them with drag and drop. There are a lot of ways we can use this functionality, but for our example we’re just going to use a basic text input.

Add/Remove and Sortable JavaScript

jQuery('.repeatable-add').click(function() {
	field = jQuery(this).closest('td').find('.custom_repeatable li:last').clone(true);
	fieldLocation = jQuery(this).closest('td').find('.custom_repeatable li:last');
	jQuery('input', field).val('').attr('name', function(index, name) {
		return name.replace(/(\d+)/, function(fullMatch, n) {
			return Number(n) + 1;
		});
	})
	field.insertAfter(fieldLocation, jQuery(this).closest('td'))
	return false;
});

jQuery('.repeatable-remove').click(function(){
	jQuery(this).parent().remove();
	return false;
});
	
jQuery('.custom_repeatable').sortable({
	opacity: 0.6,
	revert: true,
	cursor: 'move',
	handle: '.sort'
});

You can add this javascript to the custom js you’ve already created in the last step.

The first function looks for the add button and adds a new blank field row to the end of the list of fields. This is set up generically so that you can have as many of these repeatable fields as you need.

  • "field" is a cloned version of the last field row
  • "fieldLocation" reminds the script where the end of the list is
  • Find the input within "field" and rest it’s value to empty and add 1 to the numerical integer we’ll use to save the data as an array
  • Add the field after the fieldLocation

The next function gives each remove button the ability to remove that row when it is clicked.

Finally, we set the lists to be sortable and define a handle so that you can drag and drop the rows. There’s no need to enqueue the jQuery UI sortable interaction because it is already being used on the edit post page.

Create the Field

array(
	'label'	=> 'Repeatable',
	'desc'	=> 'A description for the field.',
	'id'	=> $prefix.'repeatable',
	'type'	=> 'repeatable'
)

There isn’t anything special about this field in the array for our example. However, you could get pretty crazy here and add options for what kind of fields are used in the repeatable list.

// repeatable
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>';
			$i++;
		}
	} 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>';
break;

This field requires a loop if there is a meta value saved, and no loop if there isn’t.

  • The add button can be placed anywhere outside of the <ul>.
  • Begin the unordered list with the class we set up in the javascript to target the elements within.
  • If there’s a meta value saved, loop through each value and output it with an input field and a remove button for that list item.
  • Use the $i integer to make sure a new number is added to the name array.
  • If there’s no meta value, just output one empty field
  • This is a rough handle for sorting, but it gets the job done for our example

Conclusion

If you’ve been following along with all three parts of this series so far, your final box should look like the one pictured here:

Custom Meta Box

We’ve really only scratched the surface of what can be done with this method of building a reusable custom meta box template. The more you add to your template, the easier it is to drop it into whatever project you’re working on to make the time you spend coding faster and to streamline the process with clean, consistent code.


Other parts in this series:Reusable Custom Meta Boxes Part 2: Advanced FieldsReusable Custom Meta Boxes Part 4: Using the Data
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://www.topgosip.com/ Top gossip – Celebrity apprentice

    how can do this!!
    i will try it?
    it’s my site from WP and i want to critik for you!!

    JUAL BELI ALERTPAY PAYPAL LIBERTY RESERVE

  • http://prop-14.com Randy

    Wow. This was extremely helpful. I just recently did an additional fields button with straight javascript. I like this method better though.

  • http://www.proweso.pl Paul

    Great tutorial!

  • http://www.ruturaaj.com Ruturaaj

    Nice… I was waiting for your next part. But oh dear… you still kept me waiting for “color picker”. Now that you’ve concluded your article series here, looks like the “color picker” is not on your To-Do list. :-( Tell you what… add this custom field type to your list and you will surely receive thanks from many. Custom Color for certain elements of WordPress is one of the common customization fields that Users demand these days. Needless to say, your article series is still the best, even without jQuery Color Picker! :-)

    • Vadim

      Its actually not that hard to add a colorpicker to this code. I found one and just added it.. here’s the code with color picker

      https://s3.amazonaws.com/od_downloads/metabox_code_and_colorpicker.zip

      • http://www.ruturaaj.com Ruturaaj

        Thanks so much… I just reviewed your code and found the mistakes in my code. Truly, this site has proved to be a very useful source of information for me and the credit goes to the contributors like you & Tammy.

  • jerry

    great work with clean codes;
    can you make other files more than images worked with type “image” since many other file types can be uploaded in wordpress uploader? and make it repeatable will be much greater. thanks for sharing.

    • jerry

      and now only fields are reusable, hope meta box can be reusable to create multiple meta boxes.

  • Abdulhadi

    Best series ever !!!!
    hope to see more tutorial from you Tammy

  • http://www.thomasveit.com Thomas Veit

    oooh my god! i was searching for exatly that for sooo long!! damn cool! thank you very much tammy! great! :))

  • Tomica

    This whole series is VERY cool! Thank you so much Tammy. It helps me a lot with what I’m currently working on – a dictionary.

    I wonder if the series will continue. Now THAT would be awesome, because, as you said, this was just scratching on the surface.

    Specifically, I’d love to learn how to integrate these Meta Boxes with Custom Post Types, then how to remove Title and Content from a post and leave only custom Meta Boxes inside, and finally and most important for me – Conditional Custom Fields, Custom Taxonomies and Conditional Custom Meta Boxes.

    Any chance of seeing some of that stuff soon?

    • http://www.tammyhartdesigns.com Tammy Hart

      To add these to a custom post type, simply change ‘post’ to your CPT name in the main add_meta_box call. That is line 9 of add_meta_box.php in the download.

      I’m not sure how to remove the editor and title from a post or page off the top of my head, but I know that when you’re registering your own CPT, you can leave them off of ‘supports’ in the arguments array.

      I might be able to get to your other questions in another tutorial later on.

      Hope this helps!

      • http://www.ruturaaj.com Ruturaaj

        You’re right… it’s “Supports” array that defines which default fields are to be included. For example consider this:

        ‘supports’ => array(‘title’, ‘editor’, ‘author’)

        This will enable “title”, “editor” and “author” fields for your custom post type. However, removing “title” from the Post Type is not a good idea. All posts without Title create an entry of “Auto Post” and these posts don’t show up in the list of WordPress Posts. Furthermore, you may wish to alter the columns of Post List for your Custom Post type to add extra columns to show information from one of these Custom Meta Boxes and may end up removing Title column since your Post Type does not support Title. But as a result, you will lose those “Quick Links” which show up in the first column when you move your mouse over the Title of Post thereby leaving you high and dry to handle the “Edit”, “Delete” and “View” actions entirely on your own.

        So, think twice before you decide to remove the “Title” for Post. You can always skip it while rendering your WordPress Pages as you can build custom template files specific to your Custom Post Type. Or else, if anyone knows the best way to achieve the Custom Post Type without “Title” and yet avoid running into the “Auto Draft” issue, I request you to please step-in and share your views with all of us here. :-)

        • Tomica

          Cool, thanks to you both guys!

          @Tammy yes, it sure helps. You rock!

          This just goes to show how very interesting it would be to extend this topic. /me very interested :)

        • http://www.tammyhartdesigns.com Tammy Hart
          Author

          Actually, I’m pretty sure WordPress will automatically title the post with the date. At least that’s what my experience was the one time I tried doing this.

          • http://www.ruturaaj.com Ruturaaj

            I don’t know, but my experience is different… no Date as Title; perhaps I did the same thing differently then. :-)

            I created a custom Post Type, Testimonials, for a theme I was developing. I didn’t include the support for Title and WordPress 3.2 saved the Post with the title “Auto Draft”. These Auto Drafts remain hidden from Posts list and even from the normal call of “get_posts()”, unless you specify the Post Type and retrieve the Drafts as well. I was unaware of this “Auto Draft” used as Title until I stumbled upon one of such in site search result. I went to Database to cross-check and confirmed that all my Testimonials were saved with “Auto Draft” as title.

            I used Google to see if I’m the only one who is facing this auto draft issue or otherwise… and was glad to see a few more around me who faced the same issue and discussed the possible solutions on WordPress Support forum as well as on WordPress Bug Tracker.

            Since I was running short of time, I simply added the support for Title and moved on; but frankly, that was just a time-saver for me than anything else really. I remember I read somewhere that “auto-draft” is a “post_status” which is a result of “auto save” feature and the basis for “revisions” feature in WordPress; but it does not signify the Title being Auto Draft for my custom post type.

            I’m sure there must be a solution for this; one may just start with “tite_save_pre” filter with “save_post” action. I’ve not tried this solution as yet but that was in my mind to try out with my Testimonials custom post type; in fact, like a typical time-sensitive coder, I left that issue that time with a self promise come back to that issue sometime later and honestly, that “later” is still yet to tick on my clock! :-)

  • http://www.welancers.com Aslam Doctor

    Wow, this is just perfect :)

  • http://www.sagarnangare.in Sagar

    Yet another master stroke by wp.tutsplus.com. great going !

  • http://www.dietmarhartje.de Dietmar

    Great Tutorial, I wish I had that before!

  • Vadim

    Oh wow…I’m officially set!

    Thank you very much..

  • Vadim

    One question, on the Repeatable how would you go about displaying that on the page? I’m assuming it’ll be a typical get_post_meta but how would you loop though each of the items that was added by the user?

    • Been

      Yeah, would be nice Tammy if you add in each section how to output the data.

    • http://www.tammyhartdesigns.com Tammy Hart

      A Bonus part is already in the works that will cover this. Shhhh, it’s a surprise. :)

      • Vadim

        You’re great! I’m sure we’ll be able to figuee it out if we tried..but you’re making our world a lot easier :) Appreciate your time!!!

      • http://thomasgbennett.com Thomas Bennett

        I’ve noticed my $prefix_name[0] does not work for this. After looking at the database I see why. Can’t wait for the post to get the repeatable’s on the frontend. Ideally seeing a foreach example would be helpful!

  • ralph

    great job!
    just a bit note for non english user:

    how i can change the date format according to the wp main language?

    if i change the line 159 from

    $output .= ‘jQuery(“.datepicker”).datepicker();’;

    $output .= ‘jQuery( “.datepicker” ).datepicker( jQuery.datepicker.regional[ "fr" ] );’;

    nothing happen;

    thank you

  • Gregg

    A couple of things…

    Does the textarea except html. I don’t see anything that would strip out html.

    What if I wanted to add a WYSIWYG area? I understand we can add those with 3.3.1

    Great tutorial as always.

  • John

    First up, thanks very much for producing such a great set of tutorials – it’s honestly the best set of tutorials on the topic I’ve found so far and it’s particularly timely for me seeing as I’ve just had a client ask for some fairly complex metabox stuff!

    This is more likely to be a glitch somewhere in my code but I’ve noticed that having implemented the repeating fields type something breaks on the post list page. Specifically, the checkbox that allows the user to select all posts on that page now does not select anything ) the checkbox itself checks but nothing else happens). Also, the custom fields column is maximised (if that’s the right term) as if the user has clicked read more. Just also noticed that the new admin main menu rollovers from WP3.3 no longer function.

    I’ve narrowed this down being a jQuery conflict that’s related to the custom-js.js file. In my implementation I’ve got an exact copy of your JS file and it’s enqueued in the same way (using the if is_admin conditional). However, whilst it references correctly in the head of all the admin pages it causes the glitches described above (the repeating fields in the metabox work like a charm though). When the file is removed all the glitches are gone (e.g. WP functions as it should) but of course the repeating fields no longer work.

    Was wondering if anyone else had noticed this behaviour?

    • http://www.tammyhartdesigns.com Tammy Hart
      Author

      Your javascript problems can probably be fixed by adding the dependencies to the enqueue call. See the slides from a presentation I just gave here: http://www.tammyhartdesigns.com/wordpress/enqueues-includes-defines-oh-my-the-foundations-of-plugin-theme-development/

      • http://www.goodstuffdesign.co.uk Matt

        Hi Tammy, I’ve learned so much from this tutorial, but recently had a js conflict which i’ve fixed but am uncertain if i’ve fixed ‘the right way’. All i did to fix was rename the ‘custom-js’ to ‘themename-custom-js’ – is that the best way ?

  • http://www.base8media.com base8media

    I’ve been checking everyday for this tutorial and now it’s finally here!! yea! thanks

  • Pingback: Tweet-Parade (no.2 Jan 2012) | gonzoblog.nl

  • http://www.base8media.com base8media

    I just built the image uploader an I love it, my site uses very large images however and they take up a lot of real estate on my admin screen, it there a way to set a maximum height or width for the preview (just in the post page)

    thanks in advance

    Andi

    • http://www.base8media.com base8media

      never mind, I just realized that all I have to do is set an image width attribute like so:

      . now if I could just figure out how to call the url in my template;

      style=”background-image:url(‘ .get_post_meta( $pagg->ID, ‘custom_image’, true ) . ‘) just gets me a number– the id maybe…
      hum….

  • Daneczech

    Hi there,

    fantastic scripts and tutorial but a bit tricky for non english user on certain point… I just have a problem with a major thing… How can I display the image in my theme? I callback the id of my field but I’v just a number which appears… Don’t know what to do even with searching / testing some things… I’m a beginner, so excuse me if it’s a stupid question…

    Thank you in advance ;)

    • http://www.tammyhartdesigns.com Tammy Hart
      Author

      I will be writing a follow up post about outputting all of the fields we covered in this series, but for now, you should look into the function wp_get_attachment_image(): http://codex.wordpress.org/Function_Reference/wp_get_attachment_image

    • http://www.goodstuffdesign.co.uk Matt

      I’ve actually just managed to display the image upload on my single.php – the answer is in the wp_get_attachment_image function as Tammy explains. But she has also used this function to display the image preview on your meta box already. I suggest taking a look at that code for now :-) Hope this helps

  • Michele

    Hi,
    if i want to use a multiple metaboxes, how can i change this code?

    i mean like

    $meta_boxes = array();

    // first meta box
    $meta_boxes[] = array(
    ‘id’ => ‘my-meta-box-1′,
    ‘title’ => ‘Custom meta box 1′,
    ‘pages’ => array(‘post’, ‘page’, ‘link’), // multiple post types
    ‘context’ => ‘normal’,
    ‘priority’ => ‘high’,
    ‘fields’ => array(
    array(
    ‘name’ => ‘Text box’,
    ‘desc’ => ‘Enter something here’,
    ‘id’ => $prefix . ‘text’,
    ‘type’ => ‘text’,
    ‘std’ => ‘Default value 1′
    )
    )
    );

    // second meta box
    $meta_boxes[] = array(
    ‘id’ => ‘my-meta-box-2′,
    ‘title’ => ‘Custom meta box 2′,
    ‘pages’ => array(‘post’, ‘link’), // custom post type
    ‘context’ => ‘normal’,
    ‘priority’ => ‘high’,
    ‘fields’ => array(
    array(
    ‘name’ => ‘Select box’,
    ‘id’ => $prefix . ‘select’,
    ‘type’ => ‘select’,
    ‘options’ => array(‘Option 1′, ‘Option 2′, ‘Option 3′)
    )
    )
    );

    Any help is appreciated!

  • http://www.pushplaybang.com Paul

    Brilliant tutorial series, looking forward to seeing more you here Tammy. Working though this has really helped me understand each part in the process of creating useful meta boxex, which is so seldom explained well. thank you.

  • http://www.pushplaybang.com Paul

    Hey tammy

    playing with the repeatable field, and wanted to look at repeatable post list boxes, assuming the fileds would be set as an options array, but struggling a little, any pointers? Thinking I’m punching a little above my weight with this one, but I’ll persist… next I plan to tackle it with the media uploader, but could use any suggestions.

    thanks.

    • http://www.goodstuffdesign.co.uk Matt

      Hi Paul, i just did this about 10 minutes ago when i was playing around with the code. Simply copy and paste the Repeatable output php for the or overwrite what’s already been provided with the select lists also already provided.

      • http://www.pushplaybang.com Paul

        thanks matt, haven’t had a chance to come back to this, will give it a go now, but was thinking this morning that it may be that easy, next is media upload + post select box in a repeatable, – but let me see how I get on with just the post bit first….

      • http://www.pushplaybang.com Paul

        hmmmm….. any chance of a snippet so I can see what you mean?

        • http://www.pushplaybang.com Paul

          okay so I’ve got it to generate a repeatable post select box but I have two issues. When I save it it only returns the last of the values (showing only one field), and secondly after saving a new post when adding a new field it shows the value of the field above rather than “select one”. I’m assuming this is something in the else part of the statement, but as I said, I’m punching above my weight a litttle with this one so eager to figure this out.

          I’ve posted the code below, any help would be greatly appreciated.

          case ‘repeatable’:
          $items = get_posts( array (
          ‘post_type’ => $field['post_type'],
          ‘posts_per_page’ => -1
          ));
          echo ‘+
          ‘;
          $i = 0;
          if ($meta) {
          foreach($meta as $row) {
          echo ‘|||

          Select One’; // Select One
          foreach($items as $item) {
          echo ‘ID.’”‘,$row == $item->ID ? ‘ selected=”selected”‘ : ”,’>’.$item->post_type.’: ‘.$item->post_title.”;
          } // end foreach
          echo ‘ -‘;
          $i++;
          }
          } else {
          echo ‘|||

          Select One’;
          foreach($items as $item) {
          echo ‘ID.’”‘,$row == $item->ID ? ‘ selected=”selected”‘ : ”,’>’.$item->post_type.’: ‘.$item->post_title.”;
          } // end foreach
          echo ‘-‘;
          }
          echo ‘
          ‘.$field['desc'].”;
          break;

          • paul

            hmmm thats not right….

            lets try again…. code – round two….

            case ‘repeatable’:
            $items = get_posts( array (
            ‘post_type’ => $field['post_type'],
            ‘posts_per_page’ => -1
            ));
            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>
            <select name=”‘.$field['id'].’['.$i.']” id=”‘.$field['id'].’”>
            <option value=”">Select One</option>’; // Select One
            foreach($items as $item) {
            echo ‘<option value=”‘.$item->ID.’”‘,$row == $item->ID ? ‘ selected=”selected”‘ : ”,’>’.$item->post_type.’: ‘.$item->post_title.’</option>’;
            } // end foreach
            echo ‘ </select><br /><a class=”repeatable-remove button” href=”#”>-</a></li>’;
            $i++;
            }
            } else {
            echo ‘<li><span class=”sort hndle”>|||</span>
            <select name=”‘.$field['id'].’['.$i.']” id=”‘.$field['id'].’”>
            <option value=”">Select One</option>’;
            foreach($items as $item) {
            echo ‘<option value=”‘.$item->ID.’”‘,$row == $item->ID ? ‘ selected=”selected”‘ : ”,’>’.$item->post_type.’: ‘.$item->post_title.’</option>’;
            } // end foreach
            echo ‘</select><a class=”repeatable-remove button” href=”#”>-</a></li>’;
            }
            echo ‘</ul>
            <span class=”description”>’.$field['desc'].’</span>’;
            break;

          • paul

            so the code above looks right, but the questions are gone…. here we go again…

            so the above renders a repeatable post select meta box (note that I also added post-type to the array to tell it to show posts and pages in the list) with 2 issues. First when saving it only shows the last field in the list once the page has refreshed, and secondly after the post has been saved, adding a new field shows the value of the field above it rather than the “select one” option.

            My intuition tells me that the trick is in the else part of the statement, but as i mentioned before I think I’m punching a little above my weight with this one, so any help would be greatly appreciated.

          • http://www.goodstuffdesign.co.uk Matt

            Add me to skype if you like matt.litherland and ill help you out

          • http://hugoassuncao.com hugo assunção

            i’m having the same problem: the ['.$i.'] is not increasing the number of the id, so the instance is duplicated with the same ID.
            how did you fixed it?

          • http://hugoassuncao.com hugo assunção

            I just figured it out!
            the problem was in the javascript, wich had reference for ‘input’ field instead of ‘select’ field.

  • Bram

    I’m trying to set meta boxes for different post types. No luck so far, anybody that can help me in the right direction?

    • http://goodstuffdesign.co.uk Matt

      Hi Bram,

      If you can set metaboxes for the following option: Page, Post, Custom Post Type

      The code you’re needing to alter is in Part 1of the tutorial ‘Create A Metabox’ here:
      http://wp.tutsplus.com/tutorials/reusable-custom-meta-boxes-part-1-intro-and-basic-fields/

      // Add the Meta Box
      function add_custom_meta_box() {
      add_meta_box(
      ‘custom_meta_box’, // $id
      ‘Custom Meta Box’, // $title
      ‘show_custom_meta_box’, // $callback
      ‘post’, // $page
      ‘normal’, // $context
      ‘high’); // $priority
      }
      add_action(‘add_meta_boxes’, ‘add_custom_meta_box’);

      Change ‘post’ to your Custom Post Identifier ‘my-custom-post’

      Hope this helps

      • Bram

        @Matt, hi! Thank you for your reply. What I meant was, I’m trying to create different meta boxes for multiple post-types. So custom meta boxes for pages, posts, custom post-types e.d. Can’t figure that out so far. Anybody?

        • http://www.goodstuffdesign.co.uk Matt

          It’s my understanding you cant have custom meta boxes for a specific page template but you can add global meta boxes for all pages and posts for sure, i haven’t attempted to do anything too complex.

          Again where your post identifier is just change that to “page” or “post” i think.

          http://codex.wordpress.org/Function_Reference/add_meta_box

          See reference to the Paramaters $page

          Please read it carefully as the answer IS there and IS in Part 1 of this tutorial.

          • Bram

            Yes, it is possible. Found some scripts that have the options per array

            “scope” => array( “page”, “post”, “movie” ),

            But it’s all GNU licensed.

  • http://www.goodstuffdesign.co.uk Matt

    Tammy, thanks for the resources! your time and efforts are definitely NOT unappreciated! Thank you!

  • Mic3000

    Tammy your resources are really helpful!
    It’s possible to make a repeatable fields with two or much taxonomies dropdown?
    there are any conflicts?

  • http://jamesbull.ca James Bull

    Hey Tammy, thanks for the great post!

    Been using your tutorial for a site that needs two custom post types, and I’d like to know how to save the data for two separate post types each with their own custom meta boxes.

    I thought doubling up on the save functions and defining each one with its own name would be fine, but they are both being called when the post is actually saved.

    How do I only save the data for each specific post?

    • http://ryanspilhaus.com Ryan

      Seconded – trying to add a different custom meta box to 2 different custom post types.

      • http://ryanspilhaus.com Ryan

        Never mind – figured this out. You just have to be sure to change literally ALL the functions, etc that are unique to this one.

  • http://twitter.com/MarioGiancini Mario

    This tutorial is fantastic.

    Found a way to have custom meta boxes for specific page types only:

    http://www.farinspace.com/page-specific-wordpress-meta-box/

    Awesome if you just want custom meta for a home page only.

  • http://twitter.com/MarioGiancini Mario

    I’d really like to make repeatable custom fields with file/image uploaders. I want to use them for a home page gallery. I could probably just use the repeatable text fields and make custom thumbs from the urls entered manually, but it would be nice to upload right from there.

    I tried swapping the text field for the image upload in the repeatable switch case, but I know I’m missing something in the javascript. I also got an error saying there was the foreach($meta as $row) statement was invalid.

    Any suggestions? Thanks!!

  • Pingback: My Stream » Best of Tuts+ in January 2012

  • http://www.webmentor.cr/en/ Marco Berrocal

    Hello Tammy,

    Great stuff. But one question, I have used Metaboxes previously and had to resort to a foreach loop to display them. How would you display them? Within the loop of course.

    Cheers and let me know :)

    • http://www.mattabrahams.id.au Matt Abrahams

      Here’s how I got it too work:

      php tags

      $my_custom_field = get_post_meta($post->ID, ‘your metabox id here’, true);

      foreach ( $my_custom_field as $key => $value ) {

      echo ”. $value .”;

      }

      end php tags

      • http://www.webmentor.cr Marco Berrocal

        Yah, that’s how I got it to work.

        What I don’t understand why the foreach loop then, isn’t the value of a metabox stored as an array and there is one per post? So why use a foreach?

  • Pingback: Best of Tuts+ in January 2012 | Shadowtek | Hosting and Design Solutions

  • Pingback: Best of Tuts+ in January 2012 | linuxin.ro

  • Pingback: Best of Tuts+ in January 2012 | W3schools.eu

  • Pingback: Best of Tuts+ in January 2012 | DigitalMofo

  • Pingback: Best of Tuts+ in January 2012 – blog

  • Pingback: Best of Tuts+ in January 2012 | How to Web

  • Pingback: Best of Tuts+ in January 2012 | clickshots

  • Pingback: Best of Tuts+ in January 2012 | CS5 Design

  • Max

    I have one small error when calling the media.php
    the post_id parameter is not sent
    it’s still works, there is just a php error
    as a result we don’t get the pictures attached to this post eg with the tab : gallery (2)

    it’s seems you just need to put the post_id
    custom-js.js :
    tb_show(”, ‘media-upload.php?type=image&TB_iframe=true’);
    become
    tb_show(”, ‘media-upload.php?post_id=’+id+’&type=image&TB_iframe=true’);

    where id is taken from the URL (post=…). I’m not sure it’s the right way to do it.

    Thank you very much for this serie ! And all the others !

  • Pingback: Best of Tuts+ in January 2012 | HowDoDesign

  • Pingback: My Stream | Best of Tuts+ in January 2012 | My Stream

  • Robin

    Hey Tammy, Fantastic walk through it’s been really useful.

    I just wanted to share an error I came across when implementing this into a theme I had been working on just incase anyone else has the same problems. It relates to the sortable part of the repeatable fields.

    I found that when I was in another part of the admin section I found that that it was throwing an undefined error because of the sortable function in custom-js.js. For example when if I tried to quick edit a comment then the buttons for Cancel and Update Comment would not work, this was true again for the quick edit options on pages however the sortable worked without a problem on the meta boxes. When I commented out the sortable function all the buttons regained full functionality but obviously the sortable wasn’t there.

    Long story short after banging my head against it for while I found that enqueuing jQuery-ui-sortable

    if(is_admin()) {
    wp_enqueue_script(‘jquery-ui-datepicker’);
    wp_enqueue_script(‘jquery-ui-slider’);
    wp_enqueue_script(‘jquery-ui-sortable’);
    ….

    fixed the problem and made everything play nice, I think it was more something at my end rather than the code from the walk through but just thought I’d mention it, might save someone the head ache I have had trying to work it out.

    Also to save the called incorrectly error when debugging is turned on, its worth wrapping the whole enqueue section in a function and then calling it via add_action(‘admin_enqueue_scripts’, ‘function-name’);

    Thanks again Tammy.

    • http://none Jose Luis

      hi i have the same problem, the quick edit buttons and screen options doesn´t work when you are in all post page, all pages, all custom_pot_types…etc, they work when you are inside the post editing it.
      firefox gives me this error:

      Error: jQuery(“.custom_repeatable”).sortable is not a function
      Archivo de origen:

      All the rest works perfectly

      I have recently installed Anythingslider and the button “insert slide into post” also doesn´t work.

      Please could you help me?

      I am enqueuing scripts this way

      add_action( ‘init’, ‘my_custom_js’ );
      function my_custom_js() {
      if( !is_admin() ){
      wp_deregister_script(‘jquery’);
      wp_register_script(‘jquery’, (“http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js”), false, ’1.3.2′);
      wp_register_script(‘jquery-filterable’, get_template_directory_uri() . ‘/js/filterable.js’, ‘jquery’, ”, true);
      wp_register_script( ‘greyscale’, get_template_directory_uri() . ‘/js/greyScale.js’, ‘jquery’ ,”, true );
      wp_register_script(‘jquery1′, (“http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js”), false, ’1.4.2′);
      wp_enqueue_script(‘jquery-ui-datepicker’);
      wp_enqueue_script(‘jquery-ui-slider’);
      wp_enqueue_script(‘jquery-ui-sortable’);

      wp_enqueue_script(‘jquery’);
      wp_enqueue_script(‘jquery1′);

      wp_enqueue_script(‘jquery-filterable’);
      wp_enqueue_script(‘greyscale’);
      }
      }

      I am a completely newbie.Yhanks in advance, sorry for my english

      • phpcore

        function my_custom_js() {
        if( is_admin() ){
        wp_enqueue_script(‘jquery-ui-sortable’);
        wp_enqueue_script(‘jquery-ui-datepicker’);
        wp_enqueue_script(‘jquery-ui-slider’);
        wp_enqueue_script(‘custom-js’, get_template_directory_uri().’/js/custom-js.js’);
        }

        remove all other garbage !!!!!!!!

  • Pingback: Best of Tuts+ in January 2012 | cssWOW Showcase | Css Gallery | Css Awards | Design Inspiration Tutorials

  • http://donbwhite.com Don

    Great tutorial. I’m having some issues though.

    For some reason the image uploader isn’t working and when I click on the date form the calendar that shows up has no background making it hard to see.

    Any idea why I might be having those issued?

  • Michele

    Hi,
    if i move my sortable field my wordpress won’t update my new order.
    How can i update only my new order without add new fields?

  • Xavier

    Great Tutorial
    But, I do not know how to represent the custom fields on the front end, I want to include these fields in my single.php, I need help please.

  • Anghel Gabriel

    I approve @Michele

    What is the point in having sortable fields if the fields don;t save in the proper order. :( ?

  • Anghel Gabriel

    I found a way of making sortable realy sort :).

    This is my outputed UL so you can have a look at id’s and input names. i used.

    |||

    -
    |||

    -
    |||

    -
    |||

    -

    In the javascript file you must add this lines of code in the sortable function.

    jQuery(‘.custom_repeatable’).sortable({
    opacity: 0.6,
    revert: true,
    cursor: ‘move’,
    handle: ‘.sort’,
    update: function(event,ui){
    var i = 0;
    jQuery(‘#aa_repeatable-repeatable li input’).each(function() {
    jQuery(this).attr(‘name’, ‘aa_repeatable['+ i++ +']‘);
    });
    }
    });

    After you move one of the element this piece of code will rename you inputs NAME attribute from first to last.
    So in conclusion when you will save the custom_post it will swap values.

    Simple as that :).

    • http://wp.envato.com/ Japh Thomson
      Staff

      Hi Anghel, it looks like maybe your code snippet lost something in the translation there. Don’t forget to wrap your code snippets in:
      <pre name=”code” class=”php”>
      // code here
      </pre>

      • Anghel Gabriel

        Well it was HTML there. I don’t know why the tag did’t work.

        The HTML is

        |||

        -|||

        -|||

        -|||

        -

        • http://wp.envato.com/ Japh Thomson
          Staff

          Hi Anghel, sorry but you must replace all < with &lt; and all > with &gt; for the HTML code to come through. This is just how code highlighting has to work in HTML.

    • Benni

      Actually, I don’t know why the fields are numbered at all. From my understanding, to translate the data of multiple input fields into an array. So would do the trick and also get rid of the sorting problem. I just tested it and it worked.

  • Pingback: Best of Tuts+ in January 2012 | GMancer

  • Anghel Gabriel

    Hope this time works.

    <ul id=”aa_repeatable-repeatable” class=”custom_repeatable ui-sortable”>
    <li><span class=”sort hndle”>|||</span>
    <input type=”text” name=”aa_repeatable[0]” id=”aa_repeatable” value=”" size=”30″>
    </li>
    <li><span class=”sort hndle”>|||</span>
    <input type=”text” name=”aa_repeatable[1]” id=”aa_repeatable” value=”" size=”30″>
    </li>
    <li><span class=”sort hndle”>|||</span>
    <input type=”text” name=”aa_repeatable[2]” id=”aa_repeatable” value=”" size=”30″>
    </li>
    <li><span class=”sort hndle”>|||</span>
    <input type=”text” name=”aa_repeatable[3]” id=”aa_repeatable” value=”" size=”30″>
    </li>
    </ul>

    • Charley Radcliffe

      Nice fix, Anghel Gabriel.

      What about removing items though – right now, it removes it but doesn’t write the change to the database….?

  • Brian O’Neill

    Hi, everyone. I’m quite new to WordPress, and I’ve found this series very helpful. This was just what I needed for the project I’m working on.

    Only problem is, I’m struggling to figure out how to retrieve the meta information and display it in a template. Per one of Tammy’s earlier comment replies, I did try to dig into the code for her RecipePress plugin, but very quickly got lost. : (

    I know that Tammy plans to publish an article on that topic, but if anybody has any thoughts in the meantime, please let me know!

    Thanks in advance

  • Jakub Kohout

    Hi,
    how can i call values from individual fields (metaboxes)?

    • Jakub Kohout

      I use this but it doesn’t work.

      ID, $field['custom_myoption'], true); ?>

  • Jakub Kohout

    Hi,
    how can i call values from individual fields (metaboxes)? I want to call text from text field and i used this code but it display text “array”. What do I do wrong?

    ID, $field['custom_text'], true); ?>

  • Pingback: Best of Tuts+ in January 2012 | Wptuts+

  • http://www.ooohh04.co.uk Giorgio Scappaticcio

    Hi, I tried to install a new meta_box, I followed the tutorial, and it is working. The only problem, my metabox should have 4 different select box. The first one is working fine, the other three, they don’t save the last selection.
    Can someone help me?
    Thank you very much.

    // Add the Meta Box
    function add_custom_meta_box_prop() {
    add_meta_box(
    ‘custom_meta_box_prop’, // $id
    ‘Agent Detail’, // $title
    ‘show_custom_meta_box_prop’, // $callback
    ‘property’, // $page
    ‘normal’, // $context
    ‘high’); // $priority
    }
    add_action(‘add_meta_boxes’, ‘add_custom_meta_box_prop’);
    // Field Array

    $prefix_agent = ‘custom_’;

    $custom_meta_fields_prop = array(
    array(
    ‘label’=> ‘First Agent’,
    ‘desc’ => ‘First Agent.’,
    ‘id’ => $prefix.’select_prop1′,
    ‘type’ => ‘select1′,
    ),
    array(
    ‘label’=> ‘Second Agent’,
    ‘desc’ => ‘Second Agent.’,
    ‘id’ => $prefix.’select_prop2′,
    ‘type’ => ‘select2′,
    ),
    array(
    ‘label’=> ‘Third Agent’,
    ‘desc’ => ‘Third Agent.’,
    ‘id’ => $prefix.’select_prop3′,
    ‘type’ => ‘select3′,
    ),
    array(
    ‘label’=> ‘Fourth Agent’,
    ‘desc’ => ‘Fourth Agent.’,
    ‘id’ => $prefix.’select_prop4′,
    ‘type’ => ‘select4′,
    ),

    );
    // The Callback
    function show_custom_meta_box_prop() {
    global $custom_meta_fields_prop, $post;
    // Use nonce for verification
    echo ”;

    // Begin the field table and loop
    echo ”;
    foreach ($custom_meta_fields_prop as $field) {
    // get value of this field if it exists for this post
    $meta = get_post_meta($post->ID, $field['id'], true);
    $meta1 = get_post_meta($post->ID, $field['id'], true);

    // begin a table row with
    echo ‘
    ‘.$field['label'].’
    ‘;
    switch($field['type']) {
    // select
    case ‘select1′:
    echo ”;
    echo ‘Select…’;
    query_posts(array(‘post_type’ => ‘Agent’, ‘posts_per_page’ => -1, ‘order’ => ‘ASC’ ));
    if ( have_posts() ) : while ( have_posts() ) : the_post();
    echo ”.get_the_title().”;
    endwhile; else: endif;
    echo ”.$field['desc'].”;
    break;
    case ‘select2′:
    echo ”;
    echo ‘Select…’;
    query_posts(array(‘post_type’ => ‘Agent’, ‘posts_per_page’ => -1, ‘order’ => ‘ASC’ ));
    if ( have_posts() ) : while ( have_posts() ) : the_post();
    echo ”.get_the_title().”;
    endwhile; else: endif;
    echo ”.$field['desc'].”;
    break;
    case ‘select3′:
    echo ”;
    echo ‘Select…’;
    query_posts(array(‘post_type’ => ‘Agent’, ‘posts_per_page’ => -1, ‘order’ => ‘ASC’ ));
    if ( have_posts() ) : while ( have_posts() ) : the_post();
    echo ”.get_the_title().”;

    endwhile; else: endif;
    echo ”.$field['desc'].”;
    break;
    case ‘select4′:
    echo ”;
    echo ‘Select…’;
    query_posts(array(‘post_type’ => ‘Agent’, ‘posts_per_page’ => -1, ‘order’ => ‘ASC’ ));
    if ( have_posts() ) : while ( have_posts() ) : the_post();
    echo ”.get_the_title().”;

    endwhile; else: endif;
    echo ”.$field['desc'].”;
    break;

    } //end switch

    echo ”;
    } // end foreach

    echo ”; // end table
    }
    // Save the Data
    function save_custom_meta_prop($post_id) {
    global $custom_meta_fields_prop;

    // verify nonce
    if (!wp_verify_nonce($_POST['custom_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 ($custom_meta_fields_prop as $field) {
    $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);
    }
    } // end foreach

    }
    add_action(‘save_post’, ‘save_custom_meta_prop’);
    ?>

  • Jessica Ricco

    Hello -
    First of all – Tammy, this post series is incredible helpful. The reusable fields concept is something I’ve been searching for for a long time.

    On to my question – I am trying to combine the reusable insert field with a checkbox. Basically I want the user to be able to add an li that has both a text insert field and a checkbox. This custom field is going to be used for “answers”, the overall custom post type is “questions.” I want the checkbox essentially to be how the user designates the correct answer(s).

    My code is below. I am able to add and remove text and it saves correctly. Basically what is happening is if any box is checked, they are all checked after saving. I understand why this is happening – something to do with the $c_meta and not saving each box value separately.

    Admittedly I am no expert in any of this and would appreciate any help anyone could provide.

    Thank you!

    function add_custom_meta_box() {
    add_meta_box(
    ‘answer_box’, // $id
    ‘Answers’, // $title
    ‘show_custom_meta_box’, // $callback
    ‘questions’, // $page
    ‘normal’, // $context
    ‘high’); // $priority
    }
    add_action(‘add_meta_boxes’, ‘add_custom_meta_box’);

    $prefix = ‘kn_’;

    $kn_checkbox = array(

    ‘label’ => ‘Checkbox Input’,
    ‘desc’ => ”,
    ‘id’ => $prefix.’checkbox’,
    ‘type’ => ‘checkbox’
    );
    $kn_answer = array (

    ‘label’ => ”,
    ‘desc’ => ‘Enter each possible answer. For true/false questions, enter true in one field, false in a second field. Check the box next to the correct answer(s).’,
    ‘id’ => $prefix.’answer’,
    ‘type’ => ‘text’
    );

    // The Callback
    function show_custom_meta_box() {
    global $kn_checkbox, $kn_answer, $post;

    // Use nonce for verification
    echo ‘<input type=”hidden” name=”custom_meta_box_nonce” value=”‘.wp_create_nonce(basename(__FILE__)).’” />’;

    $c_meta = get_post_meta($post->ID, $kn_checkbox['id'], true);
    $a_meta = get_post_meta($post->ID, $kn_answer['id'], true);

    // Begin the field table and loop
    echo ‘<table class=”form-table”>’;
    echo ‘<tr>

    <th><label for=”‘.$kn_answer['id'].’”>’.$kn_answer['label'].’</label></th>
    <td>’;
    echo ‘<a class=”repeatable-add button” href=”#”>+</a>
    <ul id=”‘.$kn_answer['id'].’-repeatable” class=”custom_repeatable”>’;
    $i = 0;
    if ($a_meta) {
    foreach($a_meta as $row) {
    echo ‘<li><span class=”sort hndle”>|||</span>
    <input type=”text” name=”‘.$kn_answer['id'].’['.$i.']” id=”‘.$kn_answer['id'].’” value=”‘.$row.’” size=”30″ />
    <a class=”repeatable-remove button” href=”#”>-</a>’;

    echo’<input type=”checkbox” name=”‘.$kn_checkbox['id'].’['.$i.']” id=”‘.$kn_checkbox['id'].’” ‘,$c_meta ? ‘ checked=”checked”‘ : ”,’/>
    <label for=”‘.$kn_checkbox['id'].’”>’.$kn_checkbox['desc'].’</label></li>’;

    $i++;
    }
    } else {
    echo ‘<li><span class=”sort hndle”>|||</span>
    <input type=”text” name=”‘.$kn_answer['id'].’['.$i.']” id=”‘.$kn_answer['id'].’” value=”" size=”30″ />
    <a class=”repeatable-remove button” href=”#”>-</a></li>’;
    }
    echo ‘</ul>
    <span class=”description”>’.$kn_answer['desc'].’</span>’;

    echo ‘</td></tr>’;
    echo ‘</table>’; // end table
    }

    function remove_taxonomy_boxes() {
    remove_meta_box(‘categorydiv’, ‘post’, ‘side’);
    }
    add_action( ‘admin_menu’ , ‘remove_taxonomy_boxes’ );

    // Save the Data
    function save_custom_meta($post_id) {
    global $kn_checkbox, $kn_answer;

    // verify nonce
    if (!wp_verify_nonce($_POST['custom_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

    $old = get_post_meta($post_id, $kn_checkbox['id'], true);
    $new = $_POST[$kn_checkbox['id']];
    if ($new && $new != $old) {
    update_post_meta($post_id, $kn_checkbox['id'], $new);
    } elseif (” == $new && $old) {
    delete_post_meta($post_id, $kn_checkbox['id'], $old);
    }

    // loop through fields and save the data

    $old = get_post_meta($post_id, $kn_answer['id'], true);
    $new = $_POST[$kn_answer['id']];
    if ($new && $new != $old) {
    update_post_meta($post_id, $kn_answer['id'], $new);
    } elseif (” == $new && $old) {
    delete_post_meta($post_id, $kn_answer['id'], $old);
    }

    }
    add_action(‘save_post’, ‘save_custom_meta’);

  • Remy Martin

    I was in the process of adding some extra fields onto Jeffery Ways custom post type class:

    https://github.com/JeffreyWay/Easy-WordPress-Custom-Post-Types

    and came across this post and http://wp.tutsplus.com/tutorials/creative-coding/custom-post-type-helper-class/ so I went ahead and merged them. You can check it out here:

    https://github.com/rmartindotco/WordPress-Custom-Post-Helper

    I also added wysiwyg as one of the fields. Thank you Tammy!

    • ajhx

      Hey Remy,

      Your work looks really good, thanks ! However, it looks like the js files aren’t loading, do you know why ?

      Thanks,

  • Pingback: Wordpress Leaks » Reusable Custom Meta Boxes Part 4: Using the Data

  • erik

    Hi,

    Thanx for your tutorial, gave me some new insights. Unfortunately i encountered some problems, most of which i could resolve, accept for one…

    One problem (some notices) arose when enqueueing, i had to make a function of it. But i got some issues with the visibility of the screenoptions, when i added wp_enqueue_script(‘jquery-ui-sortable’);
    everything was ok.

    add_action( ‘init’, ‘my_metabox_css’ );

    function my_metabox_css()
    {
    wp_enqueue_style(‘jquery-ui-custom’, get_template_directory_uri().’/css/jquery-ui-custom.css’);
    wp_enqueue_script(‘jquery-ui-datepicker’);
    wp_enqueue_script(‘jquery-ui-slider’);
    wp_enqueue_script(‘custom-js’, get_template_directory_uri().’/js/custom-js.js’);
    wp_enqueue_script(‘jquery-ui-sortable’);

    }

    I now have 2 notices left.
    One of them is occuring on all of the admin-pages, accept for the post en page pages.
    Notice: Trying to get property of non-object, refering to this line:
    $value = get_post_meta($post->ID, $field['id'], true);
    This is located in the // add some custom js to the head of the page
    If i delete that whole section, the notice disappears. Is the code checking for some values which it can’t find?

    My last notice is: Undefined index: custom_meta_box_nonce, referring to this line:
    if (!wp_verify_nonce($_POST['custom_meta_box_nonce'], basename(__FILE__)))
    This is located in // verify nonce, that one eludes me completely….

    Thanx,
    Erik

  • http://f-j.co Fez

    Hey guys,

    When I used this on a project the Image uploader was overriding the default functionality for send_to_editor so what I did was is save the original to a variable and then restored it at the end of the custom send_to_editor.

    Here’s the code:-

    jQuery(‘.custom_upload_image_button’).live(“click”, function() {
    //storing the original function to be restored later
    window.restore_send_to_editor = window.send_to_editor;
    formfield = jQuery(this).siblings(‘.custom_upload_image’);
    preview = jQuery(this).siblings(‘.custom_preview_image’);
    tb_show(”, ‘media-upload.php?type=image&TB_iframe=true’);
    window.send_to_editor = function(html) {
    imgurl = jQuery(‘img’,html).attr(‘src’);
    classes = jQuery(‘img’, html).attr(‘class’);
    id = classes.replace(/(.*?)wp-image-/, ”);
    formfield.val(id);
    preview.attr(‘src’, imgurl);
    tb_remove();
    //restoring the function
    window.send_to_editor = window.restore_send_to_editor;
    }
    return false;
    });

  • Pingback: Customising Repeatable Wordpress Custom Fields

  • http://www.beyeah.net Romain

    Hey,

    first of all thanks for that excellent tut. How would you do to populate field values in the cpt admin columns ?

    Thanks,

  • MGJP

    thanks man this tutorial is genius

  • http://norecipes.com Marc

    Awesome tutorial! The repeatable fields is pretty much exactly what I’ve been looking for, but I’m having trouble getting them to work. I have the JS enqeued and a view source of the edit post page shows that the JS file is loading properly. Yet, the add button is not adding a new field. Here’s my code:

    // Styles and Scripts
    add_action(‘admin_enqueue_scripts’, ‘amazonIIP_admin_enqueue’);
    function amazonIIP_admin_enqueue() {
    if(is_admin()) {
    wp_enqueue_script(‘custom-js’, plugins_url( ‘custom-js.js’, __FILE__ ));
    }
    }

    // Add the Meta Box
    function add_custom_meta_box() {
    add_meta_box(
    ‘custom_meta_box’, // $id
    ‘Amazon Item In Post’, // $title
    ‘show_custom_meta_box’, // $callback
    ‘post’, // $page
    ‘normal’, // $context
    ‘high’); // $priority
    }
    add_action(‘add_meta_boxes’, ‘add_custom_meta_box’);

    // Field Array
    $prefix = ‘custom_’;
    $custom_meta_fields = array(
    array(
    ‘label’ => ‘ASINs’,
    ‘desc’ => ‘A description for the field.’,
    ‘id’ => $prefix.’repeatable’,
    ‘type’ => ‘repeatable’
    )
    );

    // The Callback
    function show_custom_meta_box() {
    global $custom_meta_fields, $post;
    // Use nonce for verification
    echo ‘<input type=”hidden” name=”custom_meta_box_nonce” value=”‘.wp_create_nonce(basename(__FILE__)).’” />’;
    // Begin the field table and loop
    echo ‘<table class=”form-table”>’;
    foreach ($custom_meta_fields as $field) {
    // get value of this field if it exists for this post
    $meta = get_post_meta($post->ID, $field['id'], true);
    // begin a table row with
    echo ‘<tr>
    <th><label for=”‘.$field['id'].’”>’.$field['label'].’</label></th>
    <td>’;
    switch($field['type']) {
    // repeatable
    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=”15″ />
    <a class=”repeatable-remove button” href=”#”>-</a></li>’;
    $i++;
    }
    } else {
    echo ‘<li><span class=”sort hndle”>|||</span>
    <input type=”text” name=”‘.$field['id'].’['.$i.']” id=”‘.$field['id'].’” value=”" size=”15″ />
    <a class=”repeatable-remove button” href=”#”>-</a></li>’;
    }
    echo ‘</ul>
    <span class=”description”>’.$field['desc'].’</span>’;
    break;
    } //end switch
    echo ‘</td></tr>’;
    } // end foreach
    echo ‘</table>’; // end table
    }

    // Save the Data
    function save_custom_meta($post_id) {
    global $custom_meta_fields;

    // verify nonce
    if (!wp_verify_nonce($_POST['custom_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 ($custom_meta_fields as $field) {
    $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);
    }
    } // end foreach
    }
    add_action(‘save_post’, ‘save_custom_meta’);

    • http://norecipes.com Marc

      Never mind, I fixed the issue. My JS file wasn’t loading jQuery.

  • Cedric

    Excellent tutorial !

    But i have a problem with the image uploader. It can’t upload an image : after clicking the submit button in the media upload popup, it returns me a blank popup which i have to close manually and the image does not appear in the metaboxe image field.

    The console gives me this error :

    Uncaught TypeError: Cannot call method ‘replace’ of undefined // custom-js.js:17
    jQuery.click.window.send_to_editor // custom-js.js:17
    (anonymous function) // media-upload.php:4

    Any help would be greatly appreciated !

  • TC

    Hi,
    I looking a way to implementing the images uploader to my meta box, your tutorial help me a lot.

    Everything works fine, but there is one odd thing I noticed. The flash uploader seem not entirely working. When I choose an image to upload, the flash uploader have no response at all. Then I try the browser uploader, and it works fine. Then I switch back to the flash uploader and try to upload image again, and strangely this time the flash uploader work like a charm.

    So in my observation, the flash uploader only working after the browser uploader have uploaded image.

    How is this happened?

    Is it me that having this problem only?

    Thanks

  • http://martinburdon.co.uk Martin

    Hi,

    Great tutorial!

    I’ve been trying to make the repeatable field work with the image uploaded rather than the text field, I’ve replaced the text field code with the image code, however now when you click the ‘+’ button it doesnt do anything, furthermore I get the following error in the Chrome dev bar:

    Uncaught TypeError: Cannot call method ‘replace’ of undefined

    When I remove the line of code within the ‘else’ loop which inserts the upload button the ‘+’ begins to work again so I believe the error has something to do with this.

    Here is the code I have modified, I have not modified any of the JS.

    case ‘repeatable’:
    echo ‘+
    ‘;
    $i = 0;
    if ($meta) {
    foreach($meta as $row) {
    $image = wp_get_attachment_image_src($meta, ‘medium’); $image = $image[0];
    echo ‘|||

     Remove Image

    -‘;
    $i++;
    }
    } else {
    echo ‘|||

     Remove Image

    -‘;
    }
    echo ‘
    ‘.$field['desc'].”;
    break;

    Thanks in advance,
    Martin

  • http://martinburdon.co.uk Martin

    Hi,

    Great tutorial!

    I’ve been trying to make the repeatable field work with the image uploaded rather than the text field, I’ve replaced the text field code with the image code, however now when you click the ‘+’ button it doesnt do anything, furthermore I get the following error in the Chrome dev bar:

    Uncaught TypeError: Cannot call method ‘replace’ of undefined

    When I remove the line of code within the ‘else’ loop which inserts the upload button the ‘+’ begins to work again so I believe the error has something to do with this.

    Here is the code I have modified, I have not modified any of the JS.

    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) {
    $image = wp_get_attachment_image_src($meta, ‘medium’); $image = $image[0];
    echo ‘<li><span class=”sort hndle”>|||</span>
    <input name=”‘.$field['id'].’['.$i.']” type=”hidden” class=”custom_upload_image” value=”‘.$meta.’” />
    <img src=”‘.$image.’” class=”custom_preview_image” alt=”" /><br />
    <input class=”custom_upload_image_button button” type=”button” value=”Choose Image” />
    <small> <a href=”#” class=”custom_clear_image_button”>Remove Image</a></small>
    <br clear=”all” />
    <a class=”repeatable-remove button” href=”#”>-</a></li>’;
    $i++;
    }
    } else {
    echo ‘<li><span class=”sort hndle”>|||</span>
    <input name=”‘.$field['id'].’['.$i.']” type=”hidden” class=”custom_upload_image” value=”" />
    <img src=”" class=”custom_preview_image” alt=”" /><br />
    <input class=”custom_upload_image_button button” type=”button” value=”Choose Image” />
    <small> <a href=”#” class=”custom_clear_image_button”>Remove Image</a></small>
    <br clear=”all” />
    <a class=”repeatable-remove button” href=”#”>-</a></li>’;
    }
    echo ‘</ul>
    <span class=”description”>’.$field['desc'].’</span>’;
    break;

    Thanks in advance,
    Martin

    • http://nicolermccoy.com Nicole

      Martin,

      I’m sure you already found a solution by now, but I was looking for the same thing. So for the sake of posterity I figured I would put the answer on here.

      Here’s what that section of PHP should look like

      // repeatable
      case ‘repeatable’:
      echo ‘&lta class=”repeatable-add button” href=”#”&gt+&lt/a&gt
      &ltul id=”‘.$field['id'].’-repeatable” class=”custom_repeatable”&gt’;
      $i = 0;
      if ($meta) {
      foreach($meta as $row) { $image = wp_get_attachment_image_src($row, ‘medium’); $image = $image[0];
      echo ‘&ltli&gt&ltspan class=”sort hndle”&gt|||&lt/span&gt&ltinput name=”‘.$field['id'].’['.$i.']” id=”‘.$field['id'].’” type=”hidden” class=”custom_upload_image” value=”‘.$row.’” /&gt
      &ltimg src=”‘.$image.’” class=”custom_preview_image” alt=”" /&gt
      &ltinput class=”custom_upload_image_button button” type=”button” value=”Choose Image” /&gt
      &ltsmall&gt &lta href=”#” class=”custom_clear_image_button”&gtRemove Image&lt/a&gt&lt/small&gt
      &lta class=”repeatable-remove button” href=”#”&gt-&lt/a&gt&lt/li&gt’;
      $i++;
      }} else {
      $image = wp_get_attachment_image_src($row, ‘medium’);
      $image = $image[0];
      echo ‘&ltli&gt&ltspan class=”sort hndle”&gt|||&lt/span&gt
      &ltinput name=”‘.$field['id'].’['.$i.']” id=”‘.$field['id'].’” type=”hidden” class=”custom_upload_image” value=”‘.$row.’” /&gt
      &ltimg src=”‘.$image.’” class=”custom_preview_image” alt=”" /&gt
      &ltinput class=”custom_upload_image_button button” type=”button” value=”Choose Image” /&gt
      &ltsmall&gt &lta href=”#” class=”custom_clear_image_button”&gtRemove Image&lt/a&gt&lt/small&gt
      &lta class=”repeatable-remove button” href=”#”&gt-&lt/a&gt&lt/li&gt’;
      }
      echo ‘&lt/ul&gt&ltspan class=”description”&gt’.$field['desc'].’&lt/span&gt’;
      break;
      } //end switch

      The jQuery section that is the click function ‘.repeatable-add’ needs to look like this:

      jQuery(‘.repeatable-add’).click(function() {
      field = jQuery(this).closest(‘td’).find(‘.custom_repeatable li:last’).clone(true);
      fieldLocation = jQuery(this).closest(‘td’).find(‘.custom_repeatable li:last’);
      jQuery(‘input.custom_upload_image’, field).val(”).attr(‘name’, function(index, name) {
      return name.replace(/(\d+)/, function(fullMatch, n) {
      return Number(n) + 1;
      });
      })
      field.insertAfter(fieldLocation, jQuery(this).closest(‘td’))
      return false;
      });

      • http://nicolermccoy.com Nicole

        Here’s the none messed up PHP code

        // repeatable
        case ‘repeatable’:
        echo ‘+
        ‘;
        $i = 0;
        if ($meta) {
        foreach($meta as $row) { $image = wp_get_attachment_image_src($row, ‘medium’); $image = $image[0];
        echo ‘|||

         Remove Image
        -‘;
        $i++;
        }} else {
        $image = wp_get_attachment_image_src($row, ‘medium’);
        $image = $image[0];
        echo ‘|||

         Remove Image
        -‘;
        }
        echo ”.$field['desc'].”;
        break;
        } //end switch

        • Nicole

          or not… well apparently I can’t post code here. The original code I posted is right, just replace &lt and &gt. Maybe it’s helpful anyways.

  • http://www.randombell.com Jeff

    I love this tutorial and have used it in a few templates I’ve created and am creating for others.

    I have one question though:

    How would you do multiple input fields for the repeatable fields section? I’m making a template for a movie site that would allow the user to enter in the cast member and the character they played. Right now it’s all being entered into the single input but would rather have two separate input boxes (one for the cast name, one for the character name).

    How would you go about adding the second input line immediately after the first? I’ve attempted to do it myself however it always pulls the same content for both boxes after I update the page.

    Any help would be amazing. Thank you!

  • http://webdesignerart.com Abdullah

    Hi guys, I user your metabox image upload feature, In front end page when i call custom meta id. It returns image value or id :P

    i need uploaded image but how to retrive the uploaded image.

    $features_field = get_post_meta($post->ID, ‘custom_image’, true);

    echo $features_field;

    It return just value “141″.

  • Erik

    Hello and thank you for a great tutorial!

    I have a problem with the image uploader. After I upload the image I wish to use and click Insert into post the upload area just becomes white and I get this error in the console:

    classes is undefined

    id = classes.replace(/(.*?)wp-image-/, ”);

    The error seems to occur at line 17 in the file custom-js.js

    Does anyone have a clue about what’s causing this?

    /Erik

    • http://www.gradientgraphics.net Wes DeKoninck

      @Erik – I was having this problem too. I was able to solve it by replacing:

      <pre name=”code” class=”js”>
      window.send_to_editor = function(html) {
      imgurl = jQuery(‘img’,html).attr(‘src’);
      classes = jQuery(‘img’, html).attr(‘class’);
      id = classes.replace(/(.*?)wp-image-/, ”);
      formfield.val(id);
      preview.attr(‘src’, imgurl);
      tb_remove();
      }
      </pre>

      with:
      <pre name=”code” class=”js”>
      window.send_to_editor = function(html) {
      img = jQuery(html);
      imgurl = img.attr(‘src’);
      classes = img.attr(‘class’);
      id = classes.replace(/(.*?)wp-image-/, ”);
      formfield.val(id);
      preview.attr(‘src’, imgurl);
      tb_remove();
      }
      </pre>

      That should do the trick…

  • Pingback: Hacking WordPress Menus, Submenus and the Admin in General - Jean Galea | Web Designer and Developer in Malta | WordPress Consultant

  • http://www.harishchouhan.com Harish Chouhan

    Hello Tammy.

    great article. I see how you have extended this idea for your Recipress plugin. Would it be possible to let us know, how to have 1 textarea & a image upload button in a row in the repeatable fields?

    @Japh, this site needs subscribe to comments options. Would be really helpful :)

    • http://wp.envato.com/ Japh Thomson
      Staff

      Hey Harish, it certainly does! This feature is much requested (by me too!) and we are working on implementing it.

      • Arpita Patel

        Hi Japh,

        Really nice article. I also want to group up text and textarea fields in repeatable field. I tried to do it myself, but not able to get it properly working. can you please tell me when it will be ready for us to use?

        Thanks for your help.

        Arpita

  • http://aligator-studio.com AnyDog

    Hi,
    I’m getting this errors:
    Warning: Invalid argument supplied for foreach() in … \functions\add_meta_box.php on line 153
    ( foreach ($custom_meta_fields as $field) )
    and in custom box:
    Warning: Invalid argument supplied for foreach() in … \functions\add_meta_box.php on line 188
    (foreach ($custom_meta_fields as $field) )

    I don’t get it … $custom_meta_fields is valid array defined in code above these lines … I’m examine this code for hours now and just don’t get …

    Any help, pls ?
    Thanks

  • dustykhan

    Is there a away to add images and text into the custom repeatable? I have tried like below but wont add new fields and I would then be unsure how to display both elements! Please help :)

    case ‘repeatables’:
    echo ‘+
    ‘;
    $i = 0;
    if ($meta) {
    foreach($meta as $row) {
    echo ‘|||

     Remove Image
    ‘.$field['desc'].’

    -‘;
    $i++;
    }
    } else {
    echo ‘|||

     Remove Image
    ‘.$field['desc'].’

    -‘;
    }
    echo ‘
    ‘.$field['desc'].”;
    break;

  • dustykhan

    case ‘repeatables’:
    echo ‘+
    ‘;
    $i = 0;
    if ($meta) {
    foreach($meta as $row) {
    echo ‘|||

     Remove Image
    ‘.$field['desc'].’

    -‘;
    $i++;
    }
    } else {
    echo ‘|||

     Remove Image
    ‘.$field['desc'].’

    -‘;
    }
    echo ‘
    ‘.$field['desc'].”;
    break;

  • http://www.dietmarhartje.de Dietmar

    How about adding a farbtastic thing? I read in the comments that people add a colorpicker by adding something completly new allthough WordPress comes along with farbtastic plugin. But I didn’t get it to work…

  • http://victory-design.ru/ Victory

    Hello. How add to “repeatable” more inputs?

    Example:
    Text field: Title
    Text field: Description
    Checkbox: on/off

    • Ruturaaj

      Please see my answer to Charles’s question above… in case if you find it useful or perhaps point out flaws in my approach and correct me wherever you find necessary. :-)

  • http://mandooox.tk mandooox

    i have two issues :

    1- this code not work give me error

    jQuery(‘.custom_repeatable’).sortable({
    opacity: 0.6,
    revert: true,
    cursor: ‘move’,
    handle: ‘.sort’
    });

    error : Uncaught TypeError: Cannot call method ‘create’ of undefined

    2- repeatable input fields work okay, but sortable fields doesn’t work after save, still any field in last place, not change place

    • Aquanat Holding

      i get same error on

      jQuery(‘.custom_repeatable’).sortable({opacity: 0.6,
      revert: true,
      cursor: ‘move’,
      handle: ‘.sort’
      });

      how can i do?

  • Cédric

    Tks a lot Tammy. I used this solution on my new website.

    I done an wp update and my button “Choose Image” and “Remove image” don’t work now.
    “Choose image” don’t open the media iframe… do you have a solution ?

    tks a lot !

  • Pingback: WordPress. Как использовать повторяющиеся поля Custom Meta Boxes -

  • Charles

    Im trying to do multiply custom fields (5) and make them reapeatable but i cant get this work. Anyone know how to setup repeatable field which has inside 5 custom fields ?

    • Ruturaaj

      Ok, I’ve not tried it as yet, but this is what I could recollect after looking at the code. If you observe the “Add” button code, you will realize that it’s actually cloning the “LI” element. So, you will need to wrap your entire set of fields in LI inside ECHO under FOREACH loop of Repeatable. Make sure you derive unique names for each field using the ID of repeatable. Probably the simplest would be suffix your extra field name after $i. This way you will be able to preserve the increment and yet have a unique name for each field added to the set.

      Before I conclude, one small question for you… have you head of WPAlchemy Metabox PHP Class? I must submit that Tammy’s work exceeds the capabilities of this Class with her creative additions of Date and Slider controls to her set of fields. But that’s possible to implement with WPAlchemy as well. Having said this, Tammy’s code is still my favorite.

      • http://www.facebook.com/karol.klycinski Karol Kłyciński

        Thanks for the info. I have done this using WPAlchemy Class and its really amazing.

        • Ruturaaj

          Great, to hear you’ve already solved your issue. One query though… did you manage to make WPAlchemy Repeatable fields sortable like Tammy’s code?

  • hjohanstreumme

    I just found an error with the image field. Maybe it has to do with later wordpress versions? In the js file, replace the two occurances of

    jQuery(‘img’,html)

    with

    jQuery(html)

    That fixed it for me!

  • DustyKhan

    How do I order posts by date and still show posts without a date selected?

    post_parent ) { ?>

    'post', 'meta_key' => 'fund_dead', 'orderby' => 'meta_value', 'order'=>'ASC', 'category_name' => 'Big Lottery' );

    $loop = new WP_Query( $args );

    while ( $loop->have_posts() ) : $loop->the_post(); ?>

    <a href="">

    ID, 'fund_dead', true);

    $today = esc_html_e( date( '' , strtotime( $fund_dead ) ) );

    if($eventDate == $today) { ?>

    Deadline:

    Deadline: ID, 'fund_dead', true);

    esc_html_e( date( 'l, F jS, Y' , strtotime( $fund_dead ) ) ); ?>

    Eligibility: ID, 'fund_elig', true);

    echo apply_filters('', $fund_elig); ?>

    <a class="event-more" href="">Read More

  • http://twitter.com/WariiWario Devteck

    Image not work ?

    Replace in js :

    window.send_to_editor = function(html) {

    imgurl = jQuery(‘img’,html).attr(‘src’);

    classes = jQuery(‘img’, html).attr(‘class’);

    id = classes.replace(/(.*?)wp-image-/, ”);

    formfield.val(id);

    preview.attr(‘src’, imgurl);

    tb_remove();

    }

    by :

    window.send_to_editor = function(stuff) {

    //console.log(stuff);

    var data = jQuery(stuff).filter(‘img’);

    //console.log(data);

    imgurl = data.attr(“src”);

    //console.log(imgurl);

    classes = data.attr(“class”);

    //console.log(classes);

    id = classes.replace(/(.*?)wp-image-/, ”);

    formfield.val(id);

    preview.attr(‘src’, imgurl);

    tb_remove();

    }

  • Por

    I would like to know how to add extra textarea box in every single repeatable input, Please Thanks

  • Casper

    Hi, I want to repeat 2 cases, one image field and one text field. How can I combine the repeater with my desire. Thank you.

  • Jacob

    awesome and very usefull tutorial !! Thanks a lot !!!!

    but image upload doesn’t work anymore since 3.5 upgrade and the new media manager…
    tried to fix the issue searching web but nothing, i’ve integrate 3 or 4 different scripts without success….

    Any idea from anyone ? maybe a tutorial update ?
    think that many will be gratefull, me first ! :-)

  • Ryan

    Thank you Devteck, That fixed my problem perfectly. Image upload now works again.

  • alvaronicardo

    thank you for the post, I am trying to repeat 2 field instead of one as shown int he post, how I do that and how I get the value in the theme

  • Pingback: How to develop a Wordpress Theme - WordPress Theme Development Tutorials

  • http://www.rhianmolinari.com/ Rhian Molinari