Help with JavaScript to Sum Inputs Across Multiple Questions and Validate Later Response | XM Community
Skip to main content

Hello,

I’m trying to use JavaScript to calculate the sum of specific text entry fields from three earlier form questions (QID188, QID191, and QID194). I want to store that total in an Embedded Data field (DSNavigationReferral) so that I can compare it to a later response (QID423), which contains another set of text entry fields.

  • In QID188, QID191, and QID194, I want to add only the fourth text entry field from each question (e.g., QRQID1884, QRQID1914, QRQID1944).

  • I'm placing JavaScript on Q194 using addOnPageSubmit() to calculate the sum and set the Embedded Data value.

  • In Survey Flow, I’ve inserted DSNavigationReferral as an Embedded Data field after the Q194 block and before the Q423 block.

  • In Q423, I use JavaScript to compare the total entered there to the value stored in DSNavigationReferral, and disable the Next button if they don’t match.

However, the value for DSNavigationReferral always appears to be null or 0 by the time Q423 loads. The comparison doesn’t work, and no warning is triggered.

Things I’ve tried:

  • Using addOnPageSubmit() instead of questionclick()

  • Checking input field names manually via export tags

  • Confirming that the Embedded Data is declared in Survey Flow before Q423

Could you please help me determine why the Embedded Data value is not being stored correctly, or suggest a working approach for this use case?

Thank you!

I think the issue is that addOnPageSubmit() runs only when the current question is submitted, but Embedded Data is not updated in time for the next block unless explicitly set via Qualtrics.SurveyEngine.setEmbeddedData().

Do the following in Q194’s JavaScript (the last question used for input):

Qualtrics.SurveyEngine.addOnPageSubmit(function() {
let val1 = parseFloat("${q://QID1884/ChoiceTextEntryValue}");
let val2 = parseFloat("${q://QID1914/ChoiceTextEntryValue}");
let val3 = parseFloat("${q://QID1944/ChoiceTextEntryValue}");

let total = (val1 || 0) + (val2 || 0) + (val3 || 0);
Qualtrics.SurveyEngine.setEmbeddedData("DSNavigationReferral", total);
});

Also ensure that DSNavigationReferral is initialized before Q423 and no other block between Q194 and Q423 overwrites it.

I hope it helps.
-- Rochak


@mikasar12,

You probably don’t need JS. Just set DSNavigationReferral in the survey flow before Q423 using arithmetic:

DSNavigationReferral = $e{ q://QID188/ChoiceTextEntryValue/4 + q://QID191/ChoiceTextEntryValue/4 + q://QID194/ChoiceTextEntryValue/4 }

 


You are a genius!!! Thank you! For the second question, I have javascript in place that should stop the user from advancing if the total of the numbers entered does not match the embedded data point, but it isn’t working no matter what I try. Any tips?

@mikasar12,

You probably don’t need JS. Just set DSNavigationReferral in the survey flow before Q423 using arithmetic:

DSNavigationReferral = $e{ q://QID188/ChoiceTextEntryValue/4 + q://QID191/ChoiceTextEntryValue/4 + q://QID194/ChoiceTextEntryValue/4 }

 

My code: 

Qualtrics.SurveyEngine.addOnload(function () {
    var q1Total = parseFloat(Qualtrics.SurveyEngine.getEmbeddedData("DSNavigationReferral")) || 0;
    var q2Inputs = this.getQuestionTextContainer().querySelectorAll("input[type='text']");
    var nextButton = document.getElementById("NextButton");

    // Blue guidance
    var instructionMsg = document.createElement("div");
    instructionMsg.style.color = "blue";
    instructionMsg.style.marginTop = "10px";
    instructionMsg.innerText = "Please ensure the total here matches the total number of clients you listed for Navigation, Case Management, and Referral across your objectives: " + q1Total;
    this.getQuestionTextContainer().appendChild(instructionMsg);

    // Red warning
    var warningMsg = document.createElement("div");
    warningMsg.style.color = "red";
    warningMsg.style.marginTop = "10px";
    warningMsg.style.fontWeight = "bold";
    warningMsg.style.display = "none";
    warningMsg.innerText = "Please review your numbers: the numbers you entered here do not match the total clients you entered in past questions.";
    this.getQuestionTextContainer().appendChild(warningMsg);

    function getQ2Total() {
        var sum = 0;
        q2Inputs.forEach(function(input) {
            var val = parseFloat(input.value);
            if (!isNaN(val)) sum += val;
        });
        return sum;
    }

    nextButton.onclick = function(event) {
        var q2Total = getQ2Total();

        console.log("DSNavigationReferral (q1Total): " + q1Total);
        console.log("Q423 total entered (q2Total): " + q2Total);

        if (Math.round(q2Total * 1000) !== Math.round(q1Total * 1000)) {
            warningMsg.style.display = "block";
            event.preventDefault();
            event.returnValue = false;
            return false;
        } else {
            warningMsg.style.display = "none";
            return true;
        }
    };
});
 


Another approach is to use Custom Validation so that the entries add up to DSNavigationReferral. If the QID of Q423 is QID423 (it probably isn’t), then the validation condition would be something like:

Q423 Text Entry 1 Is Equal to $e{ e://Field/DSNavigationReferral - q://QID423/ChoiceTextEntryValue/2 - q://QID423/ChoiceTextEntryValue/3 }