Repeater
A plugin to repeat groups of elements.
Projects /
A plugin to repeat groups of elements.
The Repeater Plugin can be used to clone and delete a collection of items.
The element with a class of .js-repeater__item
will be repeated each time the user clicks on the .js-repeater__add
button; the new element is appended to the .js-repeater__list
element.
<div class="js-repeater">
<ul class="js-repeater__list">
<li class="js-repeater__item">
<!-- content to be repeated here -->
</li>
</ul>
<button class="js-repeater__add" type="button">Add More</button>
</div>
Use a button with a class of .js-repeater__remove
inside the .js-repeater__item
element to have the option of removing clones.
If you want to add a custom class to the cloned elements, add a data-repeater-class
attribute to the .js-repeater
element:
<div class="js-repeater" data-repeater-class="repeater__item">
<ul class="js-repeater__list">
<li class="js-repeater__item">
<!-- content to be repeated here -->
</li>
</ul>
<button class="js-repeater__add" type="button">Add More</button>
</div>
For example, you can use this class to show the .js-repeater__remove
button for clones, while keeping it hidden for the first item.
If you are using this component to clone form fields, then each clone must have input elements with different name
/id
attributes.
For the plugin to work properly, all your inputs should have name and id values equal to customName[n][inputType]
, where:
customName
: a custom label of your choice (same value for all your input elements);n
: index of the cloned element (starting from 0);inputType
: a custom label that identifies the input.Add to the .js-repeater
element a data-repeater-input-name
attribute equal to customName[n]
.
Here's an example of a repeater for a user name/email block:
<div class="js-repeater" data-repeater-input-name="user[n]">
<div class="js-repeater__list">
<fieldset class="js-repeater__item">
<div>
<label for="user[0][name]">Name</label>
<input type="text" name="user[0][name]" id="user[0][name]">
</div>
<div>
<label for="user[0][email]">Email</label>
<input type="email" name="user[0][email]" id="user[0][email]">
</div>
</fieldset>
<!-- example of a cloned element -> [n] is now [1] -->
<fieldset class="js-repeater__item">
<div>
<label for="user[1][name]">Name</label>
<input type="text" name="user[1][name]" id="user[1][name]">
</div>
<div>
<label for="user[1][email]">Email</label>
<input type="email" name="user[1][email]" id="user[1][email]">
</div>
</fieldset>
</div>
<button class="btn btn--primary js-repeater__add" type="button">Add More</button>
</div>
Note that we have added a type="button"
to the .js-repeater__add
element. This will prevent the form from being submitted when the user clicks the button.
By default, the value of each cloned input element is set to empty. If you want to use a different default value, use the data-default
attribute:
<div class="js-repeater" data-repeater-input-name="user[n]">
<div class="js-repeater__list">
<fieldset class="js-repeater__item">
<div>
<label for="user[0][name]">Name</label>
<input type="text" name="user[0][name]" id="user[0][name]">
</div>
<div>
<label for="user[0][email]">Email</label>
<input type="email" name="user[0][email]" id="user[0][email]" data-default="[email protected]">
</div>
</fieldset>
</div>
<button class="btn btn--primary js-repeater__add" type="button">Add More</button>
</div>
If you are using radio or checkbox elements and you want to set their default status to checked, use data-default="true"
:
<div>
<label for="user[0][newsletter]">Subscribe me</label>
<input type="checkbox" name="user[0][newsletter]" id="user[0][newsletter]" data-default="true">
</div>
Each time a js-repeater__item
is cloned, the itemCloned
custom event is emitted. Use this event to initialize the content of the cloned element if required:
var repeater = document.getElementsByClassName('js-repeater');
if(repeater.length > 0) {
repeater[0].addEventListener('itemCloned', function(event) {
// event.datail -> cloned element
});
}
For example, if your cloned element includes an Input Number:
var repeater = document.getElementsByClassName('js-repeater');
if(repeater.length > 0) {
repeater[0].addEventListener('itemCloned', function(event) {
initDynamicInput(event.detail);
});
}
function initDynamicInput(element) {
var inputNumber = element.getElementsByClassName('js-number-input');
for(var i = 0; i < inputNumber.length; i++) {
new InputNumber(inputNumber[i]);
}
};