Learn how to create repeater fields for your WordPress settings pages with wp.template(). That is a WordPress Underscore.js JavaScript method for getting an HTML template and passing data to it. In this tutorial, I will show you how to use wp.template() to create a repeater field.

How to use wp.template()

Before we get into creating a repeater field, we should first learn how to use it. Before using it inside our JavaScript code, we need to be sure that it is already available. To make it available we need to have the file wp-includes/js/wp-util.min.js included on the page.

How to do that? Pretty easy. When enqueuing our own javascript file, we need to make that file as a dependency. I will assume that we will place our file repeater.js inside a plugin folder in assets/js/.

By placing wp-util inside the dependency array, we are making sure that WordPress will load the wp-util.min.js on the page.

Template as Script

To use wp.template() on a template, we need to have that template placed inside a script. It would probably work otherwise also, but by using the script tag, that HTML won’t be displayed on the page.

Let’s imagine that we have an unordered list ul on a page and we want to append a new list item there with dynamic text. The template could be like this:

When getting a template with wp.template(), we are passing the template slug to that function. Then wp.template() will use that slug and check for a template with ID #tmpl-slug. That is why we have the ID tmpl-template on the script tag.

When that template is compiled the function wp.template will return a function. We can then use that function to pass a data object. That data object is then used to fill the template with the dynamic data. That is why we have the {{data.text}} inside that template.

Let’s now see how to do that:

First, we are getting the template by passing template to get the template #tmpl-template. Once that one is returned, we are using the variable template as a function by passing our data object to it.

The return value will be the compiled HTML with the dynamic data inside. We can then do with that HTML what we want such as appending it to an element.

Before creating a repeater field, you might be interested in viewing how to create a simple repeater field in this video.

Creating the Repeater Field

Now that you have a simple understanding on how this works, we can move on. The code we make here can be used elsewhere but it could require a bit of refactoring, so please read with understanding.

Let’s first create our field. This field can be used however you want, but I will assume that we are working on a meta box so I am getting the field data with the function get_post_meta.

The variable $field_data will be an array that will hold values. Each value will be a new input field. Each input field will have a remove button next to it so that we can remove it.

How to create a template now? When creating a repeater field, we need to make sure that we are getting all the required HTML inside it. The repeating HTML would start from the .field-group.

Do we need to pass anything to it? I don’t think so, since we just want to display a new input field. So, how will our template look like?

Adding Field on Click

We need to attach an event to add the field to our field group. So, how do we do that? We will use jQuery to get the template and append the HTML to our field container.

That was pretty simple. But how to handle removing inputs?

Removing Fields on Click

Removing a field will be done just by removing the .field-group from the DOM. We are doing that with this code:

We are attaching this even to the document so that even when adding a new field, the newly added remove button will be triggered.

Once the remove button is clicked, we are getting the parent element, which in this case is .field-group. After that, we are just removing it.

Conclusion

Since the idea for this tutorial is to show you how to create a repeater field, I am not showing how to save such value. The value that is passed on a $_POST request is a simple array with all the data inside the $_POST. You can directly save that or validate the array first.

When working on complex examples, you would probably need to do something more on the JavaScript part. Other than that, working with wp.template is as simple as shown in this examples.

If you are interested in how to create a repeater field in WP Customizer, you can read my other article: WordPress Customizer Flexible List Control.

If you are interested to see how to work with multiple fields, you might want to read the code of my free plugin: https://wordpress.org/plugins/raise-prices-with-sales-for-woocommerce/. The files you might be interested in are here:

Have you ever tried to build your own repeater field? Would you like seeing more examples of it? Be sure to let me know in the comments below:)

Become a Sponsor

Posted by Igor Benic

Web Developer who mainly uses WordPress for projects. Working on various project through Codeable & Toptal. Author of several ebooks at https://leanpub.com/u/igorbenic.

11 Comments

  1. Thanks for the great tutorial!

    One thing I would be interested in learning is saving repeater fields unserialized, with each item having its own meta key/value pair.

    Reply

    1. You could go through each posted field and save them separately. Maybe run a foreach loop on $_POST['field_data'] and create the meta_key based on the value or on the index.

      Be sure to use the same meta_key prefix so you can retrieve all the fields with a custom SQL query such as SELECT * FROM $wpdb->postmeta WHERE meta_key LIKE 'prefix_%' AND post_id = $post_id. Do note that you should use this query with $wpdb->prepare for $post_id.

      Reply

      1. Thanks Igor!

        That was very helpful!

        I love your tutorials, the work you put in here is much appreciated!

        Reply

  2. Thank you so much for this amazing tutorial

    Reply

  3. How to Put template Script tag to Separate file for example Repeater.tmpl (similar .vue template engine) in page ?

    Reply

    1. Hi Mehrshad, this is using the underscore.js templating engine (https://underscorejs.org/#template) with its own interpolation tags implemented (https://codex.wordpress.org/Javascript_Reference/wp.template). I am not sure you can use such system to have files separated in their own files/folders. You could do something like that but then you’ll need to develop the whole system yourself.

      Reply

  4. Hi! is it possible apply into a extend profile (xprofile) in buddypress?
    Thanks!!

    Reply

  5. Hi!
    actually i have got an problem. My add repeater button not working but remove button working fine. please check my code below and help me :

    $(document).on( ‘click’, ‘#field_data_add’, function(e){
    e.preventDefault();
    var template = wp.template(‘repeater’),
    html = template();
    $(“#field_data”).append( html );
    });

    Add

    Reply

  6. Hi ,
    Thank you for the article . Can you please put one on how to make repeater blocks in Gutenberg ?

    Reply

  7. I have searched all over the internet for help with repeater fields! So thank you for this! I can start to see how this works now. I am a nube at coding, and I’m building a very complicated WordPress site with many parent child post types. For example, I have user portfolios where they can add their projects to their portfolio post type via a relationship field. I was using ACF, but I don’t like the way things look and I’m tired of paying high prices for using other people’s plugins. I want to make my own! I could definitely use some more help in this subject to make a repeater relationship field from scratch like that. Could you recommend some other articles you have written or maybe other links and YouTube videos on making really complex repeater fields? Thanks!

    Reply

    1. Hi Linda, I am not aware of tutorials that show that but it should definitely be there on the internet. You can try checking tutorials other than WordPress related on that topic and then apply the knowledge on your project.

      Reply

Leave a reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.