Select Page

Display repeater field as accordion in Formidable forms

One of the powerful features of Formidable forms is repeated fields which allow repeating a set of fields in a Form. Formidable allows customizing how repeated records are displayed using the “Repeat layout” setting.

  • No auto-formatting: In this layout, each repeated record displayed in their original format.
  • Inline: In this layout, All fields in a repeated record is displayed in a row.
  • Grid: In this layout, repeated records are displayed in a table where fields’ labels become table header.

While these layouts are useful in various scenarios, one of the issues with these layouts is all repeated records are visible at all times. This will be a problem if the repeater has a lot of fields inside or the user has to add many repeated records. When that happens, the form will become very big and the user will have a hard time focusing on it.

We are going to address this issue in this post by adding the accordion effect to repeated records.

Step 1: Load jQuery UI library. The following code can be added to functions.php or Code Snippets plugin can be used.

wp_enqueue_script('jquery-ui', 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js', array('jquery'));
wp_enqueue_style('jquery-ui-css', 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css');

Step 2: Create the form with the repeater field and other fields the usual way.

Step 3: The next step is to make sure the repeated field and the Add & Remove buttons are displayed in the same line. Click on the repeater field and add “frm10” class to “CSS Layout classes” field setting. Click on the Add/Remove button of the repeater field and add “frm_sixth” class to “CSS Layout classes” field setting. Please note that this step needs adjustment based on your theme and page layout. You can also completely skip this and write your own CSS to do the alignment.

Step 4: Go to Settings –> “Customize HTML” in the form and edit it as per the followings instructions.

a) Identify the first field inside the repeater and add the following HTML at the beginning of it.

<div class="accordion">
  <h3><span class="accordion-title-text">Section 1</span></h3>
  <div>

b) Identify the last field inside the repeater and add the following HTML at the end of it.

  </div>
</div>

Basically what we did here is wrapping the repeater section with HTML required by accordion.

Step 5: Copy following Javascript to the “After fields” section.

<script type="text/javascript">
jQuery(document).ready(function($) {
	$(document).on("accordioncreate", '.accordion', function(event, ui) {
		setAccordionTitles();
		$('.accordion').not(this).accordion('option', {active: false});
	});
	
	createAccordion();
	$(document).on('frmAfterAddRow', createAccordion);
	$(document).on('frmAfterRemoveRow', setAccordionTitles);

	function createAccordion() {
		$( ".accordion:not(.ui-accordion)" ).accordion({
			collapsible: true, active: 0, heightStyle: "content",
			beforeActivate: function( event, ui ) {
				if(!ui.oldPanel.length) {
					$('.accordion').not(this).accordion('option', {active: false});
				}
			}
		});
	}

	function setAccordionTitles() {
		$("h3.ui-accordion-header .accordion-title-text").each(function (index, value) { 
			$(this).text("Member " + (index + 1));
		});
	}
});
</script>

If you read the above Javascript, you will know a little secret. What we are creating is not a single accordion with multiple sections. Instead, each repeater record is an accordion with a single section. If you have 10 rows in your repeater, there will be 10 independent accordions each with one section. I chose this approach because I couldn’t find a way to integrate single accordion with Formidable HTML. The above Javascript does the magic of turning all of the accordions behaving like a single accordion.

In line 25, the title of the accordion section is set. If you want a different name for the title, replace the text “Member ” with your text.

Step 6: Add necessary CSS in “Formidable” –> “Styles” –> “Custom CSS” to make the layout fit your website. The styles vary depends on your theme and other settings. The following styles are used in the example below.

.frm_repeat_buttons {
	float:right !important;	
}

.ui-accordion {
	float: left !important;
	width: 80%;
}

.ui-accordion-header {
	padding: 6px 0 !important;
	background: #F9E79F !important;
	border-color: #F9E79F !important;
}

.ui-accordion-header.ui-state-active {
	background: #F1C40F !important;
}

Demo

The following is an example form. Play with it by adding a few more repeater records and then try to expand records one after another to see the accordion effect.

Family registration form

Family registration form

Family members

Section 1

Formidable date field offset value

[Update] Formidable Forms now supports “offset” attribute. So this custom code is no longer required.

Formidable Forms [date] shortcode is used to get the current date. If a date relative to the current date is required, the offset attribute can be used.
e.g. [date offset='+3 weeks'] will return the date three weeks from today.

However, this is not true when a date field value is displayed using [x] shortcode where x is the field id or key. The [x] shortcode doesn’t support the offset attribute. But it is very easy to extend it with a few lines of custom code.

Here are some examples for a date field with id 123

[123 offset='+2 weeks']
[123 offset='-1 month']
[123 offset='+1 year 3 weeks']
[123 offset='Next Monday']
[123 offset='Last Friday']
[123 offset='First day of this month']
[123 offset='Last day of next month']

The offset attribute can be used together with format attribute which is already supported by Formidable.
e.g. [123 offset='+2 weeks' format='m/d/Y']
Replace 123 with your field ID.

Add the following code to your functions.php or use Code Snippet plugin to enable this functionality.

add_filter('frmpro_fields_replace_shortcodes', 'frm_city_date_offset', 10, 4);
function frm_city_date_offset( $replace_with, $tag, $atts, $field ) {
    if ($field->type == 'date' and isset($atts['offset']) and $replace_with) {
		$replace_with = date('Y-m-d', strtotime($replace_with . $atts['offset']));
    }
    return $replace_with;
}

Display multi-select option values in Formidable

In Formidable Forms, dropdown and checkbox fields allow selecting multiple options. If you’d like to display selected values in a view, you’d normally use [x] shortcode just like any other field where x is your field id or key. This will by default display values separated by a comma.
e.g. Apple, Orange, Cherry

A different separator can be specified using the sep attribute. For example, [x sep=" | "] will display Apple | Orange | Cherry

This opens up many possibilities. For example, options can be displayed as a list using
<ol><li>[x sep='</li><li>']</li></ol>

  1. Apple
  2. Orange
  3. Cherry

However, this approach has its limitations because we can only control what is in between two options using sep attribute. What if we want to format option values individually without any limitations. This is the question Phil asked in the Formidable’s community Slack group.

With a little custom code, we are going to extend the functionality to the next level.
The new pattern attribute can be used to specify a pattern to display an option value. The pattern can be any text where all occurrences of {} will be replaced by the option value.
e.g. <ol>[x pattern='<li>{}</li>']</ol> will display the options as a list (same as before but more easy to write and understand).

  1. Apple
  2. Orange
  3. Cherry

Not only that, it can now do what is not possible before. For example, the following shortcode displays the option values as a list with a link to Google image search. Notice that the pattern uses {} twice, one for search query inside the link URL and another one as the link text.
<ol>[x pattern='<li><a href="http://www.google.com/images?q={}">{}</a></li>']</ol>

  1. Apple
  2. Orange
  3. Cherry

When the pattern attribute is used, the default comma separator is ignored. However, if a separator is required, it can be specified using the same sep attribute.
e.g.
<ol>[145 pattern='<li><a href="http://www.google.com/images?q={}">{}</a></li>' sep='<li>---------</li>']</ol> will add a separator item between options on the list.

  1. Apple
  2. ———
  3. Orange
  4. ———
  5. Cherry

Add the following code to your functions.php or use Code Snippet plugin to enable this functionality.

add_filter('frmpro_fields_replace_shortcodes', 'frm_city_display_option_values_with_pattern', 10, 4);
function frm_city_display_option_values_with_pattern( $replace_with, $tag, $atts, $field ) {
    if ( isset ( $atts['pattern'] ) ) {
		if($replace_with){
			$pattern = $atts['pattern'];
			if(is_array($replace_with)){
				foreach($replace_with as $key => $value) {
					$replace_with[$key] = str_replace('{}', $value, $pattern);
				}
				$replace_with = implode($atts['sep'], $replace_with);
			} else {
				$replace_with = str_replace('{}', $replace_with, $pattern);
			}
		}
    }
    return $replace_with;
}

Auto-increment ID in Formidable forms

Formidable Forms [auto_id] shortcode is used to set an unique and auto-incrementing value to form entries. Example usecases include serial number, job number and invoice number.

By default, numbers start from 1 but it can be changed with “start” attribute.
e.g. [auto_id start=1000]

A prefix and/or suffix can be added by simply adding letters before and/or after the shortcode.
e.g. SN[auto_id start=1000]A
This will generate SN1000A, SN1001A, SN1002A, .... and so on.

One of the limitations of the shortcode is, prefix/suffix can’t have numbers. If numbers included, it could result in unexpected values. However, adding zeros as the prefix will work since leading zeros have no effect on a number. We might tempt to use it generate a serial number with a fixed number of digits like 001, 002, 003, … using 00[auto_id]. But the issue is after 10, it will become 0010 instead of 010. In order to dynamically add leading zeros, following custom code can be used.

add_filter('frm_pre_create_entry', 'format_auto_number');
function format_auto_number($values){
  if ( $values['form_id'] == 27 ) {//Replace 27 with your Form ID
    //Replace 126 with your field ID.
    //Here 3 in sprintf function represents number of fixed digits.
    $values['item_meta'][126] = sprintf("%03d", $values['item_meta'][126]);
  }
  return $values;
}

Refresh the page after updating a field value in Formidable forms

Formidable Forms provides an easy way to update a field value with a click on a link. However one of its shortcomings is, if the value being updated by the link is visible on the page, it is not updated to its new value as shown below.

In this post, we are going to fix it by introducing a custom shortcode which utilizes existing Formidable code where possible and enhance it where it is required.

Step 1:
Create a new shortcode frm_city_entry_update_field which replaces the Formidable Javascript function frmUpdateField in the link with a modified function frmCityUpdateField. Add this to functions.php or use Code Snippets plugins which is our preferred method for adding custom scripts.

add_shortcode('frm-city-entry-update-field', 'frm_city_entry_update_field');
function frm_city_entry_update_field( $atts ) {
	//Call Formidable forms function which is used by original shortcode
	$link = FrmProEntriesController::entry_update_field($atts);
	
	//Inject enhanced version of Javascript code which supports page refresh and confirmation message options.
	if(!empty($link)) {
		preg_match('/(?<=frmUpdateField)\([^\)]*\)/', $link, $matches);
		if($atts['confirmation_msg']){
			$confirm_script = "onclick=\"if(confirm('" . $atts['confirmation_msg'] . "')){frmCityUpdateField" . $matches[0] . ";}return false;\"";
		} else {
			$confirm_script = "onclick=\"frmCityUpdateField" . $matches[0] . "; return false;\"";			
		}
		$link = preg_replace('/onclick=\"[^\"]*\"/', $confirm_script, $link);
	}
	return $link;
}

Step 2:
frmCityUpdateField Javascript function is identical to frmUpdateField function except it refreshes the page upon successfully updating the field. Here we used Code Snippet plugin to inject Javascript code. If you use a different approach, you may have to copy only the Javascript part which starts with <script> and end with </script>

add_action( 'wp_head', function () { ?>
	<script>
		function frmCityUpdateField(entry_id, field_id, value, message, num) {
			jQuery(document.getElementById("frm_update_field_" + entry_id + "_" + field_id + "_" + num)).html('<span class="frm-loading-img"></span>');
			jQuery.ajax({
				type: "POST",
				url: frm_js.ajax_url,
				data: {
					action: "frm_entries_update_field_ajax",
					entry_id: entry_id,
					field_id: field_id,
					value: value,
					nonce: frm_js.nonce
				},
				success: function() {
					if (message.replace(/^\s+|\s+$/g, "") === "")
						jQuery(document.getElementById("frm_update_field_" + entry_id + "_" + field_id + "_" + num)).fadeOut("slow");
					else
						jQuery(document.getElementById("frm_update_field_" + entry_id + "_" + field_id + "_" + num)).replaceWith(message);

					location.reload();
				}
			})
		}
	</script>
<?php } );

Step 3:
Use the new shortcode frm-city-entry-update-field in place of frm-entry-update-field shortcode. All attributes of the shortcode will work as usual.

e.g.
[frm-city-entry-update-field id=[id] field_id=205 value="Open" label="Open this venue"]

Bonus:
As an added bonus, frm-city-entry-update-field provides an optional confirmation_msg attribute to which prompts the user to confirm before updating the field value.

e.g.

[frm-city-entry-update-field id=[id] field_id=205 value="Open" label="Open this venue" confirmation_msg="Are you sure want to Open this Venue?"]