How to Use Pre-transition JavaScript in a Workflow Action to Evaluate Line Items Before Submission

Created by Joshua Miller, Modified on Mon, 23 Mar at 10:32 AM by Joshua Miller

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 true so 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:

  1. Open the workflow
  2. Open the action, such as Submit
  3. Go to Client Actions
  4. Paste the JavaScript into Pre-transition Action
  5. 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 0 through 99
  • For each index, it looks for a field from that row
  • If the field exists, the row exists
  • Each time a row is found, totalRows increases 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 rows
  • rowsChecked: how many rows have the completion checkbox set to true
  • rowsForHodgeTX: how many rows match specific Dubuque departments
  • rowsForHodgeTXChecked: how many of those Dubuque rows are complete
  • rowsForHodgeDW: how many rows match specific Davenport departments
  • rowsForHodgeDWChecked: how many of those Davenport rows are complete

Then it sets these fields:

  • customString8 to "true" or "false" depending on whether all rows are completed
  • customBool2 to true or false depending 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

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article