Custom WordPress and WooCommerce Development

Options framework repeating field showing several text inputs and an "Add" button

Add a Repeating Text Field to Options Framework Plugin

Options framework repeating field
This is what we’ll be building.
I don’t hardly even know why I was working on this today.  Well a friend wanted to be able to control the radio buttons in a metabox, from the backend (since the otherwise brilliant WP-Alchemy is all dev-level coding) and for some reason  my brain went to theme option.  He ultimately went a different route and used Advanced Custom Fields.  But some days I just feel like not working and doing something fun, and the question of repeating fields in the theme options piqued my interest.  I asked Devin Price if his awesome Options Framework plugin has such a thing and he replied that no it didn’t exist…. yet. He wasn’t sure it was possible, which is like the worst thing to say to me. Of course it is possible! And now instead of working on something responsible, I will now solve this riddle. So I started digging into Options Framework. At first I thought that I would fork OF, but it turns out that all the functions/filters needed are already in place!   Wherever you have your $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”

  1. 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 );

    1. 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)

  2. 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.

    1. 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.

  3. 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/

    1. 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!

  4. 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

    1. 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

  5. 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.

    1. 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.

      1. Rahul Patil Avatar
        Rahul Patil

        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!

        1. I’d probably suggest trying to group all the input fields into an array some_group[field1][] and some_group[field2][]. Maybe that way all the info could still be saved in the some_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.

  6. 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.

    1. 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.

  7. 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.

    1. 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.

  8. kathy,

    I can’t show the output. Can you please write a demo code to show output.

    Thanks in advance.
    Ashik

    1. 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 sample foreach may help:

      $options = of_get_option( 'example_repeat' ); 
      if( ! empty( $options ) ){
          echo '<ul>';
          foreach( $options as $option ){
              echo '<li>' . $option . '</li>';
          }
          echo '</ul>';
      }