$options
array in your theme’s options.php to get a repeating field you’d define your custom option like so:
// add this to your $options array
$options[] = array(
'name' => __('Repeating Text', 'options_framework_theme'),
'desc' => __('A repeating text input field.', 'options_framework_theme'),
'id' => 'example_repeat',
'std' => 'Default',
'type' => 'repeat_text');
Then to handle all the parts of displaying this, scripting the repeat, and validating the data you’ll need the following group of functions, added to your theme’s functions.php.
Creating the Output
First, we need to output something when Options Framework gets running and encounters the custom option of type ‘repeat_text’. Devin has a catch-all filter already built-in, so we just have to attach a function to the {$option_type}_option_type
filter, in this case repeat_text_option_type
. This callback will create the input box (as many as needed by the array of values) plus one hidden one. It also creates the “Add New” button and for good fun we’ll throw in delete buttons next to each input. The markup (and later the script to handle the repeat) draws a lot of inspiration for WP Alchemy’s repeating groups.
// add this to your theme's functions.php
/* * Define a custom option type * this type will repeat some text inputs */
function repeat_text_option_type( $option_name, $option, $values ){
$counter = 0;
$output = '<div class="of-repeat-loop">';
if( is_array( $values ) ) foreach ( (array)$values as $value ){
$output .= '<div class="of-repeat-group">';
$output .= '<input class="of-input" name="' . esc_attr( $option_name . '[' . $option['id'] . ']['.$counter.']' ) . '" type="text" value="' . esc_attr( $value ) . '" />';
$output .= '<button class="dodelete button icon delete">'. __('Remove') .'</button>';
$output .= '</div><!–.of-repeat-group–>';
$counter++;
}
$output .= '<div class="of-repeat-group to-copy">';
$output .= '<input class="of-input" data-rel="' . esc_attr( $option_name . '[' . $option['id'] . ']' ) . '" type="text" value="' . esc_attr( $option['std'] ) . '" />';
$output .= '<button class="dodelete button icon delete">'. __('Remove') .'</button>';
$output .= '</div><!–.of-repeat-group–>';
$output .= '<button class="docopy button icon add">Add</button>';
$output .= '</div><!–.of-repeat-loop–>';
return $output;
}
add_filter( 'optionsframework_repeat_text', 'repeat_text_option_type', 10, 3 );
Sanitation and Saving
Options Framework won’t save anything unless the data gets run through a sanitization filter. The neat thing, is that if you set up the input names as name="somefield[1]"
and so on, WordPress will automatically save all the “somefield” fields in an array. So we just need to rifle through the array and sanitize each text field. We can do this quickly with array_map
. Next
/*
* Sanitize Repeat Fields
*/
function sanitize_repeat_field( $input, $option ){
$clean = '';
if( is_array( $input ) )
$clean = array_map( 'sanitize_text_field', $input);
return $clean;
}
add_filter( 'of_sanitize_repeat_text', 'sanitize_repeat_field', 10, 2 );
Style and Scripting the Repeating Fields
Finally, all the bells and whistles. What good is a repeating field if it doesn’t, you know, repeat. Again, I have to credit Dimas Begunoff for his WP Alchemy class. I’ve simplified some of what he was doing in metaboxes, by merely adding a data-rel
to the hidden input. Then a few quick on
handlers for the button click events and that hidden input we created earlier gets cloned and given a proper name attribute. Clicking a delete button, removes it’s associated input from the DOM.
/*
* Custom repeating field scripts
* Add and Delete buttons
*/
function of_repeat_script(){ ?>
<style>
#optionsframework .to-copy {display: none;}
#optionsframework .of-repeat-group {
overflow: hidden;
margin-bottom: 1.4em;
}
#optionsframework .of-repeat-group .of-input {
width: 80%;
}
.of-repeat-group .dodelete {
float: right;
}
</style>
<script type="text/javascript">
jQuery(function($){
$(".docopy").on("click", function(e){
// the loop object
$loop = $(this).parent();
// the group to copy
$group = $loop.find('.to-copy').clone().insertBefore($(this)).removeClass('to-copy');
// the new input
$input = $group.find('input');
input_name = $input.attr('data-rel');
count = $loop.children('.of-repeat-group').not('.to-copy').length;
$input.attr('name', input_name + '[' + ( count - 1 ) + ']');
});
$(".of-repeat-group").on("click", ".dodelete", function(e){
$(this).parent().remove();
});
});
</script>
<?php
}
add_action( 'optionsframework_custom_scripts', 'of_repeat_script' );
Output
Because we’ve saved an array of data the if you try to echo out the results of of_get_option('example_repeat');
you will get Array
. You have to loop through the array to print out each on individually with a foreach
loop.
This is definitely beta-ish. For instance, I know it doesn’t take into account a way to set an array of defaults… like if you wanted to have two fields set up as the default. Maybe it is Google Chrome, but I’m also having a little issue with tab indexing. And finally… there was something else, but my mind just went blank. Get the full code from my Gist. As beta code, I am totally open to suggestions and improvements, but I won’t be able to help you set this up on your own sites. I’m just putting it out there for information purposes only. What would you use a repeating field for in theme options?
Comments
18 responses to “Add a Repeating Text Field to Options Framework Plugin”
You are awesome!! It works great.
I modified sanitize_repeat_field() to output conditionally as array_map() expects an array, but there is none when all the inputs are removed .
function sanitize_repeat_field( $input, $option ){
$output = is_array( $input ) ? array_map( 'sanitize_text_field', $input ) : $input;
return $output;
}
add_filter( 'of_sanitize_repeat_text', 'sanitize_repeat_field', 10, 2 );
I’m glad it helped you… I thought it was a fun problem to work on. I’m not sure how your code is different? I’ve also checked for an `$input` array, and in the case where there isn’t one just send back blank data. Wouldn’t you risk sending back unsanitized strings? (Not that there should be any, but you’re never supposed to trust user input)
Great post.
This is one of the things i noticed missing with options frameworks, which is why i started using advanced custom fields, which has a great options page too.
But i noticed some conflicts using ACF on some themes and I haven’t been able to dig enough to figure out why, and support their has been only minimally helpful.
I wonder if you might comment on the advantages of using the topions framework for theme options as opposed to using something like ACF.
Thanks.
I’m not familiar enough with ACF to really make a comparison. I thought ACF was for metaboxes though, whereas OF is for theme options. I’ve always liked that OF is super developer-friendly and you can wrap it into your theme either with a plugin dependency, or include the whole files.
You may want to checkout ReduxFramework. It has this field built in by default and many more.
NHP just merged with Redux too. It’s a really powerful framework.
http://wordpress.org/plugins/redux-framework/
Wow, I just looked through the demo and that’s a really impressive looking framework you have there. I’ll definitely keep that bookmarked in case I ever need to build a theme again!
Hey Kathy,
Awesome work with this! Big fan.
Just wondering if there is anyway that this kind of thing would be possible, but applying it to the WooThemes framework. Basically I add my custom options as an extension (tab) to theirs (the ones that are already included in the theme), but I’m DYING to be able to add a repeater field like this.
I’m using their Canvas theme by the way.
At present their only ‘type’ options are the usual radio, text, textarea, checkbox etc…
Any ideas?
Thanks.
Luke
Hi Luke,
I’ve never really looked in to it. There is an action/default hook in the switch statement that prints out the option depending on its type (See admin-interface.php), so you can’t really hook into anything and add your own type. I’d suggest tweaking Canvas (all Woo themes use the same framework) and sending it to Woo to see if they might consider adding it to future releases. You could either build the full repeater field and suggest it, or it is more likely they’d add a hook for the default case. Technically you could override the entire `woothemes_machine($options)` function but that seems a bit overkill. Or maybe you could just rely on the “text” input type and then use javascript on the rest. I’m sure there *is* a way, it is just a matter of how elegant it may or may not be.
Good luck,
-kathy
Hi!
Very good job! I have one question…
Is it possible to add more inputs on one click? I tried to add second input to function repeat_text_option_type() but values don’t save correctly.
Thanks.
You mean a group of repeating fields? I suppose it is possible, but you’ll have to write custom display and save (or sanitization) callbacks. It sounds like you’ve got the `repeat_text_option_type()` mostly sorted, but need to get `sanitize_repeat_field()` figured out. (This assumes you have the input names correct, which I couldn’t even tell you what correct would be). I haven’t looked at this in almost a year, so it isn’t really fresh for me. Sorry, I can’t be more helpful.
I am looking for the same solution. Repeating group of fields, I would be using it for dynamic slider.
It would be great if you help me!
I’d probably suggest trying to group all the input fields into an array
some_group[field1][]
andsome_group[field2][]
. Maybe that way all the info could still be saved in thesome_group
option? I don’t know. If you want to hire me I might be able to look into it further. If so, you can use the form on my contact page. For a slider, there are a gazillion slider plugins that you could probably integrate.I am trying to put a tab under home settings?Under home setting there will be four fields.What do you think is it possible to create tab under tab.Please let me know.
I’m not completely clear what you are asking, but as with most things WordPress it is almost assuredly possible. However, it isn’t something I can get into right now. Good luck.
I mean in the option panel i have categorised the fields under different tabs like General,home settings.But what i need is that cre tab under Home Setting Or put headlines under tabs.Am I clear at this time?Please let me know.
Like I said, I am sure it is possible, but I try to stay away from support in the comments. I also have too many projects on my plate at the moment that I can’t look into it right now. I would suggest you try asking in the official Options Framework forum.
kathy,
I can’t show the output. Can you please write a demo code to show output.
Thanks in advance.
Ashik
As I described in the tutorial the option is an array of values so to display it you need a
foreach
loop. Without dusting this project off to test it, the following sampleforeach
may help: