How to Use Pre-Transition JavaScript in a Workflow to Evaluate a Request Before Submission
Pre-transition JavaScript lets you inspect and update request data right before a workflow action is completed. This is useful when you want to validate line items, count how many rows exist in a repeating section, check whether all required rows are complete, or set hidden fields that drive later workflow behavior.
The example below shows how to loop through a line item section, count the rows, evaluate values in each row, and then write results back to the request before the Submit action finishes.
What Pre-Transition JavaScript Does
A pre-transition action runs before the workflow moves from one state to the next. In this step, you can:
- Read request field values
- Read line item values
- Count rows in a repeating section
- Check row-level conditions
- Set other fields on the form
- Allow or block submission
In your example, the script does all of the following before submission:
- Counts how many line item rows exist
- Counts how many rows are marked complete
- Counts rows that belong to specific departments
- Counts how many of those department rows are complete
- Sets form fields based on the results
- Returns
trueso the workflow can continue
Where This Code Is Used
This code belongs in the Pre-transition Action area of a workflow action, such as Submit.
Typical path:
- Open the workflow
- Open the action, such as Submit
- Go to Client Actions
- Paste the JavaScript into Pre-transition Action
- Save and test
This allows the request to be evaluated right before it moves into the next workflow state.
Understanding the Data Structure
In a line item section, each row is stored using a field naming pattern like this:
line_extendedfieldDepartmentList_extendedfieldIsCompletedBool_0 line_extendedfieldDepartmentList_extendedfieldIsCompletedBool_1 line_extendedfieldDepartmentList_extendedfieldIsCompletedBool_2
The number at the end is the row index.
That means your code can check each possible row by building the field name dynamically:
"line_extendedfieldDepartmentList_extendedfieldIsCompletedBool_" + index
If that property exists in formScope.formdata, then that row exists.
How the Script Determines the Number of Line Item Rows
The row count is determined by looping through a range of possible row indexes and checking whether the row field exists.
Example:
var totalRows = 0; for (var index = 0; index < 100; index++) { if (formScope.formdata.hasOwnProperty("line_extendedfieldDepartmentList_extendedfieldIsCompletedBool_" + index)) { totalRows++; } }
How this works
- The loop checks indexes
0through99 - For each index, it looks for a field from that row
- If the field exists, the row exists
- Each time a row is found,
totalRowsincreases by 1
This gives you the number of rows currently in the line item section.
Why this is useful
Once you know how many rows exist, you can:
- Require all rows to be completed before submit
- Perform different logic when only one row exists
- Perform extra checks when there are multiple rows
- Set flags based on whether certain rows meet conditions
Example Use Case From Your Script
Your code counts:
totalRows: total number of line item rowsrowsChecked: how many rows have the completion checkbox set to truerowsForHodgeTX: how many rows match specific Dubuque departmentsrowsForHodgeTXChecked: how many of those Dubuque rows are completerowsForHodgeDW: how many rows match specific Davenport departmentsrowsForHodgeDWChecked: how many of those Davenport rows are complete
Then it sets these fields:
customString8to"true"or"false"depending on whether all rows are completedcustomBool2totrueorfalsedepending on whether all required Hodge rows are completed for the selected location
Step-by-Step Breakdown of the Script
1. Create variables to hold your counts
var totalRows = 0; var rowsChecked = 0; var rowsForHodgeTX = 0; var rowsForHodgeTXChecked = 0; var rowsForHodgeDW = 0; var rowsForHodgeDWChecked = 0;
These variables store totals you will calculate while reading the request.
2. Loop through possible line item rows
for (var index = 0; index < 100; index++) {
This checks up to 100 possible rows. If your form might contain more than 100 rows, increase the limit.
3. Check whether each row exists
if (formScope.formdata.hasOwnProperty("line_extendedfieldDepartmentList_extendedfieldIsCompletedBool_" + index)) { totalRows++;
This confirms the row exists by checking for one of the fields in that row.
4. Read values from each row and apply logic
Example from your code:
if (formScope.formdata["line_extendedfieldDepartmentList_extendedfieldIsCompletedBool_" + index] === true) { rowsChecked++; }
This counts how many rows are marked complete.
You can do the same for any line item field:
- department
- amount
- status
- checkbox
- date
- text field
5. Set form-level fields based on results
Your script sets:
if (totalRows === rowsChecked) { formScope.formdata["customString8"] = "true"; } else { formScope.formdata["customString8"] = "false"; }
This means all rows are complete only when the number of completed rows equals the number of existing rows.
Then it sets another field:
if (rowsForHodgeTX === rowsForHodgeTXChecked && formScope.formdata.multiLocation === '701091') { formScope.formdata["customBool2"] = true; } else if (rowsForHodgeDW === rowsForHodgeDWChecked && formScope.formdata.multiLocation === '701090') { formScope.formdata["customBool2"] = true; } else { formScope.formdata["customBool2"] = false; }
This allows later workflow logic to use the result.
6. Return true to let the workflow continue
return true;
Returning true allows the transition to continue.
If you wanted to stop submission, you could return false after showing a message or setting a validation condition, depending on how your platform handles client-side workflow validation.
This code is for specific factories and will need to be adjusted based on location IDs.
var totalRows = 0;
var rowsChecked = 0;
var rowsForHodgeTX = 0;
var rowsForHodgeTXChecked = 0;
var rowsForHodgeDW = 0;
var rowsForHodgeDWChecked = 0;
for (var index = 0; index < 100; index++) {
var completedField = "line_extendedfieldDepartmentList_extendedfieldIsCompletedBool_" + index;
var deptField = "line_extendedfieldDepartmentList_customLookup6_" + index;
if (formScope.formdata.hasOwnProperty(completedField)) {
totalRows++;
var isCompleted = formScope.formdata[completedField] === true;
var deptCode = formScope.formdata[deptField];
var location = formScope.formdata.multiLocation;
if (isCompleted) {
rowsChecked++;
}
// Dubuque
if (
location === '701091' &&
(deptCode === '004' || deptCode === '104')
) {
rowsForHodgeTX++;
if (isCompleted) {
rowsForHodgeTXChecked++;
}
}
// Davenport
if (
location === '701090' &&
(
deptCode === 'E98' ||
deptCode === 'ROD3' ||
deptCode === 'ROD4' ||
deptCode === 'WHS3' ||
deptCode === 'WHS4' ||
deptCode === '883' ||
deptCode === '745' ||
deptCode === '846' ||
deptCode === '748' ||
deptCode === 'NMRP' ||
deptCode === 'SCSI' ||
deptCode === 'S98' ||
deptCode === 'RTNV' ||
deptCode === '799' ||
deptCode === '751' ||
deptCode === 'TODW' ||
deptCode === 'TOWH' ||
deptCode === 'TOWW' ||
deptCode === 'I98' ||
deptCode === '782' ||
deptCode === '416'
)
) {
rowsForHodgeDW++;
if (isCompleted) {
rowsForHodgeDWChecked++;
}
}
}
}
// All rows complete
formScope.formdata["customString8"] = (totalRows === rowsChecked) ? "true" : "false";
// Hodge complete flag
if (formScope.formdata.multiLocation === '701091') {
formScope.formdata["customBool2"] = (rowsForHodgeTX === rowsForHodgeTXChecked);
} else if (formScope.formdata.multiLocation === '701090') {
formScope.formdata["customBool2"] = (rowsForHodgeDW === rowsForHodgeDWChecked);
} else {
formScope.formdata["customBool2"] = false;
}
return true;
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article