Skip to main content

Drag and drop repeater rows – Formidable Forms

This demo shows how you can use jQuery UI to apply click & drag functionality to Formidable Forms Repeaters and re-order the rows as required. We have combined this with a row counter to add extra functionality when reviewing your data in the back end.

The demo below shows each of the repeater field layout options; Default, Inline and Grid.

DEMO - Re-Order Repeater

Default Repeater

Inline Repeater

Grid Repeater

How to achieve this:

The solution to this is actually quite simple and uses the jQuery UI plugin that we also used in our drag & drop fields demo.

The first thing to do is to build your form:

  1. Add a repeater field to your form and select the formatting of your choice: Default, Inline or Grid.
  2. Add some fields to your repeater.
  3. Add a hidden or text field to your repeater that will be used as the row counter.
  4. Save your form.
  5. Go to the form Settings > Customise HTML > Before fields section and add the following:
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="/wp-includes/js/jquery/jquery.ui.touch-punch.js"></script>

What this does: This adds the jQuery UI plugin to your form and also includes the jQuery UI touch punch script so the drag and drop feature will work on touch enabled devices like smart phones and tablets.

Next, add this script directly underneath:

<!-- Default Repeater -->
<script type="text/javascript">
   document.addEventListener("DOMContentLoaded", updateRepeatCountFields );
   jQuery(document).on('frmAfterAddRow', updateRepeatCountFields );
   jQuery(document).on('frmAfterRemoveRow', updateRepeatCountFields );
   
   function updateRepeatCountFields(){
   var countFields = document.querySelectorAll( '.frm_field_2064_container input');
       for ( var i = 0, len=countFields.length; i<len; i++ ) {
           countFields[i].value = i+1;
       }
   }
   
   jQuery(document).ready(function($){
     jQuery(".frm_add_form_row").click(function(){
       $( '#frm_field_2059_container' ).sortable({
           cursor: "grabbing",
           stop: function () {
               var countFields = document.querySelectorAll( '.frm_field_2064_container input');
               for ( var i = 0, len=countFields.length; i<len; i++ ) {
                   countFields[i].value = i+1;
               }
           }
       });
     });
   });
</script>

Change 2059 to the ID of your repeater field and 2064 to the ID of your hidden or text field in 2 places.

Next scroll down and find the HTML for the repeater field you added and replace all of it with this:

<div class="ListContainer">
   <h3 class="frm_pos_[label_position][collapse_class]">[field_name]</h3>
   <div id="frm_field_[id]_container" class="frm_form_field frm_section_heading form-field[error_class]">
      [collapse_this]
   </div>
   [if description]
   <div class="frm_description">[description]</div>
   [/if description]
</div>

Now save the form.

View your form on the front end and you will see the default behaviour of the repeater row. At this stage the jQuiry UI script hasn’t been called yet as your repeater only has 1 row but when you click on the ‘Add‘ button for the first time the script will be called and you will then be able to click and drag your rows into any order you wish.

You will also see the row number field updating as you re-order the rows as per the examples above.

The final thing to do is to apply some styling to make it look a bit nicer and also work well with your theme.

Here is some example CSS that we used for the above demo:

/* Drag & Drop CSS */

.ListContainer h3 {
	font-size: 20px !important;
	line-height: 28px !important;
}

.divider-block {
	display: block;
	width: 100%;
	border-top: 2px dashed #eaeaea;
	margin-top: 50px;
	padding-top: 20px;
}

.ListContainer {
	overflow: hidden;
}

.ListContainer>div {
	white-space: nowrap;
	overflow-x: auto;
	overflow-y: hidden;
}

.frm_repeat_sec,
.frm_repeat_inline {
	background-color: #fff;
	border: 1px solid #eaeaea !important;
	padding: 20px !important;
	margin: -1px 0 auto !important;
}

.frm_repeat_grid {
	background-color: #fff;
	border: 1px solid #eaeaea !important;
	padding: 20px 20px 0 20px !important;
	margin: -1px 0 auto !important;
}

#sortable {
	margin: 0 !important;
}

.ui-sortable>div {
	cursor: move;
	cursor: grab;
	cursor: -moz-grab;
	cursor: -webkit-grab;
}

.ui-sortable>div:before {
	content: "\f047";
	display: block;
	position: absolute;
	top: 5px;
	right: 10px;
	font-size: 22px;
	color: #999;
	font-family: FontAwesome;
}

.ListContainer .form-field {
	animation-name: none !important;
}

.ui-sortable-helper {
	box-shadow: 0 10px 50px rgba(0, 0, 0, 0.08), 0 13px 45px rgba(0, 0, 0, 0.08);
}

.frm_repeat_sec:first-of-type,
.frm_repeat_inline:first-of-type,
.frm_repeat_grid:first-of-type {
	border-top-right-radius: 4px;
	border-top-left-radius: 4px;
}

.frm_repeat_sec:last-child,
.frm_repeat_inline:last-child,
.frm_repeat_grid:last-child {
	border-bottom-right-radius: 4px;
	border-bottom-left-radius: 4px;
}

.ListContainer>div {
	padding-top: 1px;
}

You will probably need to adjust the CSS above to work with your theme and website styling. In particular the use of the FontAwesome icon might not work with your website but this can be adjusted as required.

Please note: This solution is still in development and may change as we do further testing. We suggest implementing this solution on a test form before adding it to any live forms.