Forsta API Method Examples
Forsta HX Platform - API Scripting Guide
Forsta API Method Examples
Using Forsta-Specific Methods
These examples use Forsta HX native methods like .domainValues(), .item(), .toBoolean(), and .set()
Example 1: Sum Multiple Checkbox Values
// Calculate total from selected checkboxes with numeric values
var totalSpend = 0; // Initialize total to zero
// Get array of all possible option codes for this checkbox question
var codes = f('BQ4c').domainValues();
// Loop through each option code
for (var i = 0; i < codes.length; i++) {
// Check if this specific option is selected (returns true/false)
if (f('BQ4c').item(codes[i]).toBoolean()) {
// If selected, get its numeric value and add to running total
totalSpend = totalSpend + f('BQ4c').item(codes[i]).toNumber();
}
}
// Set the calculated total to the TotalSpend question
f('TotalSpend').set(totalSpend);
console.log('Total: ' + totalSpend); // Log for debugging
Example 2: Count Selected Items
// Count how many checkboxes are selected
var selectedCount = 0;
var codes = f('AQ1').domainValues();
codes.forEach(function(code) {
if (f('AQ1').item(code).toBoolean()) {
selectedCount++;
}
});
f('SelectedCount').set(selectedCount);
Example 3: Check for Specific Combinations
// Check if user selected both option "1" AND option "3"
var hasOption1 = f('BQ2').item('1').toBoolean();
var hasOption3 = f('BQ2').item('3').toBoolean();
if (hasOption1 && hasOption3) {
f('BQ2a').show(); // Show follow-up
} else {
f('BQ2a').hide();
}
Example 4: Calculate Average from Grid
// Calculate average rating from selected scale items
var codes = f('CQ1').domainValues(); // Get all option codes
var sum = 0; // Initialize sum
var count = 0; // Initialize counter
// Loop through each option
for (var i = 0; i < codes.length; i++) {
// Check if this option is selected
if (f('CQ1').item(codes[i]).toBoolean()) {
// Add the numeric value to sum
sum += f('CQ1').item(codes[i]).toNumber();
count++; // Increment count of selected items
}
}
// Calculate average (prevent division by zero)
// Ternary operator: condition ? valueIfTrue : valueIfFalse
// .toFixed(2) rounds to 2 decimal places
var average = count > 0 ? (sum / count).toFixed(2) : 0;
// Set the calculated average
f('AverageRating').set(average);
Example 5: Validate Minimum/Maximum Selections
// Ensure user selects between 2-5 options
function validateSelectionRange() {
var codes = f('DQ1').domainValues();
var selectedCount = 0;
codes.forEach(function(code) {
if (f('DQ1').item(code).toBoolean()) {
selectedCount++;
}
});
if (selectedCount < 2) {
alert('Please select at least 2 options');
return false;
}
if (selectedCount > 5) {
alert('Please select no more than 5 options');
return false;
}
return true;
}
Example 6: Get Selected Values as Array
// Build array of selected numeric values
function getSelectedValues(qid) {
var codes = f(qid).domainValues();
var values = [];
codes.forEach(function(code) {
if (f(qid).item(code).toBoolean()) {
values.push(f(qid).item(code).toNumber());
}
});
return values;
}
// Usage
var selected = getSelectedValues('EQ1');
console.log('Selected values:', selected); // [10, 25, 50]
var total = selected.reduce(function(sum, val) {
return sum + val;
}, 0);
Example 7: Set Multiple Values
// Pre-populate questions with calculated values
var income = 50000;
var taxRate = 0.25;
var afterTax = income * (1 - taxRate);
f('Income').set(income);
f('TaxRate').set(taxRate * 100); // Show as percentage
f('AfterTax').set(afterTax);
Example 8: Compare Two Questions
// Check if same items selected in two different questions
function compareSelections(q1, q2) {
var codes = f(q1).domainValues();
var matches = 0;
codes.forEach(function(code) {
var q1Selected = f(q1).item(code).toBoolean();
var q2Selected = f(q2).item(code).toBoolean();
if (q1Selected && q2Selected) {
matches++;
}
});
return matches;
}
// Usage
var matchCount = compareSelections('AQ1', 'BQ1');
f('MatchCount').set(matchCount);
Example 9: Generate Unique Patient ID (Production Only)
/**
* threeDigitString - Pads a number to 3 digits with leading zeros
* @param {number} iNum - The number to pad (e.g., 1, 12, 123)
* @returns {string} - Zero-padded string (e.g., "001", "012", "123")
* @description Converts a number to a string and prepends zeros
* until the string is exactly 3 characters long.
* Useful for generating sequential IDs like "P001", "P002".
*/
function threeDigitString(iNum) {
var sNum = String(iNum); // Convert number to string
// Keep adding leading zeros until we have 3 digits
while (sNum.length < 3) {
sNum = "0" + sNum; // Prepend a zero
}
return sNum; // Returns "001", "002", etc.
}
// Only run this in production environment
if (IsInProductionMode()) {
// Check if userid field has a value
if (f('userid').toBoolean()) {
var patNum = 1; // Start with patient number 1
var patNumString = threeDigitString(patNum); // Convert to "001"
// Create unique ID: userid + patient number (e.g., "john001")
var uidPatString = f('userid').toString().toLowerCase() + patNumString;
// Keep incrementing until we find a unique ID not in database
while (isFieldValueTaken('uidPatnum', uidPatString)) {
patNum++; // Try next number
patNumString = threeDigitString(patNum); // Format it
// Rebuild the unique string
uidPatString = f('userid').toString().toLowerCase() + patNumString;
}
// Only set PatientNumber if it doesn't already have a value
if (!f('PatientNumber').toBoolean()) {
f('PatientNumber').set(patNum); // Save the patient number
}
}
}
Key methods: .toBoolean() checks if field exists, .toString() converts to string, IsInProductionMode() ensures production environment, isFieldValueTaken() validates uniqueness on server.
Example 10: Check Field Exists Before Setting
// Only set value if field doesn't already have one
if (!f('UniqueID').toBoolean()) {
var newID = generateUniqueID();
f('UniqueID').set(newID);
}
// Check if field has value
if (f('userid').toBoolean()) {
console.log('User ID exists: ' + f('userid').toString());
} else {
console.log('No user ID found');
}
Example 11: Loop Through Grid and Set Patient IDs
// Generate patient IDs for each row in a loop/grid question
// Get array of all row codes (e.g., ["1", "2", "3"])
var arrRows = f('ePatId').domainValues();
// Loop through each row in the grid
for (var i = 0; i < arrRows.length; i++) {
var iRow = parseInt(arrRows[i]); // Convert row code to integer
var patSuffix; // Variable to store the suffix we'll generate
// Check if this is a test ID
if (isTestID()) {
// TEST MODE: Use simple numeric suffix like "P001", "P002"
var sRow = String(iRow); // Convert row number to string
// Pad with leading zeros to make 3 digits
while (sRow.length < 3) {
sRow = "0" + sRow; // "1" → "001"
}
patSuffix = "P" + sRow; // Result: "P001", "P002", etc.
}
else if (f('userid').toBoolean()) {
// PRODUCTION MODE: Generate unique suffix based on user
var uid = f('userid').get(); // Get the user ID
patSuffix = generatePatSuffix(uid, iRow); // Custom function
}
// If we successfully generated a suffix
if (patSuffix) {
// Combine user ID with suffix (e.g., "john" + "P001" = "johnP001")
var patId = f('userid').get() + patSuffix;
// Set this value for the specific row in the grid
// .item(arrRows[i]) targets the specific row
// .set(patId) sets the value for that row
f('ePatId').item(arrRows[i]).set(patId);
}
}
Key pattern: Use f('Qid').item(code).set(value) to set values for specific rows in loop/grid questions.