Sort Multi Step Form Fields

By: Fabian Pontén | Asked: 04/12/2023
ForumsCategory: Code HelpSort Multi Step Form Fields
Fabian PonténFabian Pontén asked 2 years ago
Hey folks!

I have a multi-step form and would like to sort/reorganize the form fields on Step 3 based on what the user has answered in Step 2.

Form Overview:
- The user goes through 5 Steps in total, each step contains 36 "statements" that the user will rate in different ways on each step.

In Step 2, the user will select a few values related to each statement with a total value ranging from 3 (lowest) to 9 (highest) which I can then add up to a hidden field to sum up the values to calculate which statements have the highest total score (so far so good!)

On Step 3, I want to display the statements first that got the highest values from Step 2, if that makes sense.
Here's an example to further illustrate:

Step 2
1. Statement 1 - User selects value: 3
2. Statement 2 - User selects value: 9
3. Statement 3 - User selects value: 6

Step 3
1. Statement 2 - Shows up first because it's the highest
2. Statement 3 - Shows up second because it's the middle
3. Statement 1 - Shows up third because it's the lowest

Does anyone have any idea how to do this? :) 

I got this suggestion from FF's new AI support feature, but doesn't seem to work and not sure which part isn't working:

  To sort the fields on Step 3 based on the user's answers in Step 2, you can use a combination of conditional logic and JavaScript. Here's how you can achieve this: 1. Add a hidden field to Step 2 that will store the total value of each statement. You can use a calculation field to add up the values of the selected options and store the result in the hidden field. 2. In Step 3, add all the statement fields in the order that you want them to appear initially. 3. Add a JavaScript field to Step 3 that will sort the fields based on the hidden field value from Step 2. Here's an example code snippet that you can modify to suit your needs:  
Start your code here
// get the hidden field value from Step 2 var statementValues = [form.getFieldById(‘ADD_FIELD_ID’).getValue(), form.getFieldById(‘ADD_FIELD_ID’).getValue(), form.getFieldById(‘ADD_FIELD_ID’).getValue()]; // sort the statement fields based on the values var statementFields = [form.getFieldById(‘ADD_FIELD_ID'), form.getFieldById(‘ADD_FIELD_ID'), form.getFieldById(‘ADD_FIELD_ID')]; statementFields.sort(function(a, b) { return statementValues.indexOf(b.getValue()) - statementValues.indexOf(a.getValue()); }); // remove the initial statement fields and add them back in the sorted order var container = document.getElementById('frm_field_3_container'); while (container.firstChild) { container.removeChild(container.firstChild);
Victor Font replied 2 years ago

Instead of posting the generic code suggested by ChatGPT, would you please post your modified version in pastebin and provide a link here so we can see the actual code you're using.

Victor Font replied 2 years ago

One other thing, you can't just sort the fields without their wrappers. Formidable wraps fields in multiple divs. You sort from the top level div for the field where the div id is frm_field_9999_container. Change 9999 to the id of your field.

Fabian PonténFabian Pontén replied 2 years ago

Thank you so much Victor, please see my answer with attached screenshot and the code link, really appreciate your help!

1 Answers
Fabian PonténFabian Pontén answered 2 years ago

Thank you for your reply @Victor Font! Here's a link to the code: https://pastebin.com/59C2F3y2 I put this in the Settings -> Customize HTML -> "After fields", but didn't do me any good 😊  You are correct that it seems that it's the frm_field_#_container that needs to be organized, please see my attached screenshot.

It's these divs that I would like to re-order based on the result in the previous step of the form.

Thank you so much!

Victor Font replied 2 years ago

Your code is not correct. You have a mix of straight quotes and curly quotes. Notice how the first few lines are color coded and then the color coding stops, this is an indication that the code is wrong. JSlint your code to find the numerous coding errors. You have almost 20 errors: https://www.jslint.com/

Fabian PonténFabian Pontén replied 2 years ago

Ah ok, I think maybe I fixed those errors now but I'm not sure if this code is correct still? Says something is wrong with the for loop but don't see why. But still, not sure if this code is correct anyway to achieve what I'm trying to achieve?

https://pastebin.com/hSnMMP4n

Thank you so much Victor, hope you have a great weekend!

Victor Font replied 2 years ago

chatGPT wrote code that is completely wrong. Let's walk through your code. Look at this line:

var statementValues = [form.getFieldById("3986").getValue(), form.getFieldById("3988").getValue(), form.getFieldById("3989").getValue()];

You've misidentified all of the fields; "3986", "3988", and "3989" are NOT HTML element IDs. You identify element IDs by examining the HTML in your browser inspection tool. HTML IDs are signified by the id="" in the target element. Formidable does not use field IDs when creating the element's HTML ID. Formidable uses the field key. HTML field IDs are "field_[key]" in Formidable's HTML template. For example, if the field key for field "3986" is "e6lis62", the HTML ID for the HTML input is "field_e6lis62".

We also use jQuery for accessing Formidable elements. Taking you line above and refactoring it for jQuery, it looks like this:

jQuery(document).ready(function($) {
"use strict";
var statementValues = [$("#field_conf_29yf4d2").val(), $("#field_e6lis62").val(), $("#field_9jv0r12").val()];
});

Change the HTML IDs to your IDs.

Fabian PonténFabian Pontén replied 2 years ago

Ah ok very good to know, I put the Field IDs from the fields in the FF form builder.

What about the second part of the code? Will this reorder the fields or is this also wrong you think?

statementFields.sort(function(a, b) {
return statementValues.indexOf(b.getValue()) - statementValues.indexOf(a.getValue());
});

// remove the initial statement fields and add them back in the sorted order
var container = document.getElementById("frm_field_2349_container");

while (container.firstChild) {
container.removeChild(container.firstChild);
}

Also, what about placing them back onto the page after they've been reordered? Any ideas on how to do that? 🤔

Thank you very much!

Victor Font replied 2 years ago

For the rest of this code, you're going to have to figure out how to sort the divs, since the divs do not have a value tied to the input field. The divs use the underlying field ID in the HTML id. This is probably a little confusing since you're depending on AI to write your code. However, understanding how Formidable works will save a huge amount of time in the future.

What this all means is that you need to cross reference the div IDs with the field IDs. The easiest way to do this programmatically is to create an object instead of using an array. The example line from above refactored as an object is:

var statementValues = {"#frm_field_969_container": jQuery("#field_conf_29yf4d2").val(), "#frm_field_970_container": jQuery("#field_e6lis62").val(), "#frm_field_971_container": jQuery("#field_9jv0r12").val()};

This outputs the following object:

Object { "#frm_field_969_container": "3", "#frm_field_970_container": "1", "#frm_field_971_container": "2" }
"#frm_field_969_container": "3"
"#frm_field_970_container": "1"
"#frm_field_971_container": "2"

Victor Font replied 2 years ago

Sorting requires yet another change to the Array of objects. That first line again is now:

var statementValues = [{div: "#frm_field_969_container", value: jQuery("#field_conf_29yf4d2").val()}, {div: "#frm_field_970_container", value: jQuery("#field_e6lis62").val()}, {div: "#frm_field_971_container", value: jQuery("#field_9jv0r12").val()}];

We also need a second array of objects to sort.

var sortedOrder = [{div: "#frm_field_969_container", value: jQuery("#field_conf_29yf4d2").val()}, {div: "#frm_field_970_container", value: jQuery("#field_e6lis62").val()}, {div: "#frm_field_971_container", value: jQuery("#field_9jv0r12").val()}];

Now we have to create a function to sort the array of objects by value:

function compareValues(a, b) {
return a.value - b.value;
}

To sort, we use:

sortedOrder.sort(compareValues);

The rest of the code you need is very complex. As a community volunteer, I do not have the time to spend the next few hours writing and testing code to fix the chatGPT mess it created.

What you need to do is loop through the arrays and use the jQuery.replaceWith() function to replace the divs in order from bottom to top. In order to do this, you have to duplicate the divs themselves with:

var div1 = jQuery("#frm_field_969_container"), div2 = jQuery("#frm_field_970_container"), div3 = jQuery("#frm_field_971_container")

Sorting in this manner does not carry forward the field values. This means you have to reset the values after you perform the replacement.

Working this code out with all of its permutations will take a few hours. If you need the help of a developer, please visit https://formidable-masterminds.com/developers-directory/. I gone as far as I can go as a community volunteer, but at least you're on the right track now.

Fabian PonténFabian Pontén replied 2 years ago

Thank you so much for taking your time Victor to assist me in this issue, I will see if I can figure it out and hire a developer otherwise. Really appreciate it, all the best to you!

Making the Best WordPress Plugin even better - Together

Take on bigger projects with confidence knowing you have access to an entire community of Formidable Experts and Professionals who have your back when the going gets tough. You got this!
Join the community
crossarrow-right