BookmarkSubscribeRSS Feed

Building a Form in SAS Model Risk Management (Part 1)

Started yesterday by
Modified yesterday by
Views 52

Forms are one of the most powerful tools you can add to an object page. Instead of relying on users to interpret and enter data manually, a well-built form guides them through a structured set of questions and does the work for them. In this post, we are going to build a Priority Assessment form for the Change Request object that scores five criteria and automatically assigns a priority band the moment a user makes a selection.

 

To do that, we need to start in the embedded builder.

 

If you've only worked in Cirrus Builder, the embedded builder might feel familiar at first glance, but it's a different tool. Rather than living in your schema configuration, it runs inside a Form object instance at runtime. You build directly inside the form, laying out widgets and writing interactions without touching anything outside of it.

01_KJ_Screenshot-2026-04-22-151129.png

The Change Request form on the Change Request page.

 

 

Before we start building, there are two things you need to know upfront.

 

First, once you link a form to an object record and save it, it locks. You can't edit it after that point, so build it, test it, and make sure it's working exactly the way you want before you link it to anything.

 

Second, the form by itself does not hold onto data. When a user fills it in, their answers sit temporarily in the Embedded Builder Page (EBP) component on the parent Change Request page. Persisting that data to the actual record is handled on the object side, which is what Part 2 covers.

 

The Scenario

 

Your IT Change Management team is tired of manually deciding how urgently a change request needs to be prioritized. Two people looking at the same request can come to completely different conclusions about whether it is Low priority or Critical, and that inconsistency is causing real problems: under-resourced critical changes, over-escalated minor ones, and a review process that relies too much on whoever happens to be in the room.

 

The solution is a standardized Priority Assessment that lives directly on the Change Request page. When a requestor raises a change, they answer five structured questions. The form adds up their answers automatically and assigns a priority label: Low, Medium, High, or Critical.

 

By the end of this post, you will have a fully working form with five scoring dropdowns, an automatic total score, a color-coded result, and an interaction that does all the calculation the moment a user makes a selection.

 

What We're Building

 

To get this form working, there are five things we need to do:

 

  1. Create the Form instance
  2. Add the five scoring dropdowns with numeric option values
  3. Add the output widgets that display the score and result
  4. Create the interaction that reads the dropdowns, calculates the score, and writes the result
  5. Test the form

 

Let's work through each one.

 

 

Step 1: Creating the Form Instance

 

Go to your Forms object manager table and create a new Form instance.

 

02_KJ_Screenshot-2026-04-22-151450-1024x579.png

 

You need three things:

 

  • Form ID - your internal identifier. We will use: IT_change_priority_assessment.
  • Form Name - this is what users see when a form is selected from a page. We will use: IT Change Priority Assessment.
  • Usage Type – this is the object we will associate this form with. We will use: Change Request.

 

Save the draft.

 

03_KJ_Screenshot-2026-04-22-151635-1024x602.png

 

Adding Text Labels

 

Scroll down until you find the embedded form builder. This is where you design the layout.

 

This form will have a 2-column layout: column 1 is for the Rich text labels and column 2 will include the dropdowns.

04_KJ_Screenshot-2026-04-22-151129-1.png

In both columns, there will be 4 main sections: Impact, Urgency, Risk, and Priority Score.

05_KJ_Screenshot-2026-04-22-151129-2.png

For this form, we will be using these components: 

 

  • Rich Text
  • Dropdown
  • Input Number
  • Color Dropdown

06_KJ_Screenshot-2026-04-22-151129-3.png

Section 1: IMPACT (column 1)

 

  1. From the Components menu, add a Rich Text component into the Builder panel.
  2. Change the ID to ‘Text_Impact’.
    1. Change the Text Content:

 

IMPACT

 

Business Impact 

 

How broadly does this change affect business operations? 

 

(view in My Videos)

 

Repeat these steps for the following sections:

 

Section Component ID Text Content
IMPACT Rich Text Text_Impact

IMPACT Business Impact

 

How broadly does this change affect business operations?

IMPACT Rich Text Text_Systems

Systems Affected

 

How many systems or integrations are involved?

URGENCY Rich Text Text_Time

URGENCY

 

Time Sensitivity

 

How time-critical is this change?

 

URGENCY Rich Text Text_Compliance

Regulatory or

Compliance Driver

 

Is this change required to meet a regulatory deadline?

RISK Rich Text Text_Risk

 

RISK

 

Implementation Risk

 

How likely is this change to cause disruption if it fails?

 

PRIORITY SCORE Rich Text Text_Score PRIORITY SCORE

 

You can also add the subtext as Help text. You can do so in the Properties menu of the rich text component. 

 

Click Save.

 

After adding each component, your builder panel should like something like this:

 

08_KJ_Screenshot-2026-04-22-155517-1024x530.png

 

The next part is adding in the dropdown menus and their values.

 

Step 2: Adding Dropdowns with Values

 

Since we are expecting an output score based on the dropdown selections, we will need to assign number values to each dropdown option.

 

After adding each dropdown, click Save.

 

ID Label

Option 1

Label

Option 1

Value

Option 2

Label

Option 2

Value

dd_businessImpact Business Impact 1 - Minimal 1 5 - Enterprise 5
dd_systemsAffected Systems Affected 1 - Isolated 1 5 - Cross-System 5
dd_timeSensitivity Time Sensitivity 1 - Flexible 1 5 - Immediate 5
dd_complianceDriver Compliance Driver 1 - None 1 5 - Hard Deadline 5
dd_implementationRisk Implementation Risk 1 - Low 1 5 - High 5

 

Click Save.

 

(view in My Videos)

 

Your form should look something like this:

 

08_KJ_Screenshot-2026-04-22-161916-1024x689.png

 

Step 3: Output Components

 

The last piece of the front end puzzle is adding the output components to the form. One is for the number score and the other is the label associated with the total score.

 

Priority Score

 

Add an Input Number component in the same row as the Priority Score rich text.

 

ID: priorityScore

 

Label: Priority Score

 

Check the box next to ‘Display this input number as read-only text’.

 

Click Save.

 

09_KJ_Screenshot-2026-04-22-162250-1024x566.png

 

Result Label

 

Add a Color Dropdown component under the Input Score dropdown.  

 

ID: labelResult

 

Label: Result

 

Check the box next to ‘Display this dropdown as read-only text’.

 

Add four dropdown options:

 

Label Value Color Hex Code
Low Low #7AF787
Medium Medium #F7D27A
High High #FF9999
Critical Critical #EB502A

 

Click Save.

 

 

Now, that we have the front end components, the next part is adding functionality to these dropdowns and output labels. This is achieved using Interactions. 

 

Step 4: Create the Interaction

 

Click the business impact dropdown component.

 

From the right-hand menu, select Interactions.

 

For the OnChange item action, create a new interaction called calculateScore. This means every time a user changes any answer, the interaction runs immediately and recalculates the result. The user sees a live score as they work through the form.

 

(view in My Videos)

 

Here is the full interaction, broken into four parts. Each part does a specific job, and understanding what each function does and why will help you adapt this pattern to other forms. We will be using the Script Editor to create the interaction steps.

 

Part 1: Read Each Dropdown and Convert It to a Number

 

Before the interaction can do any math, it needs to read each dropdown and make sure the value is actually a number. This part handles both of those things: it reads the value, checks whether the user has selected anything yet, and converts the result to a number if they have.

 

#Step 1 - Reads the value,
#checks whether the user has selected anything yet
#and converts the result to a number if they have.
local.rawImpact = data.dd_businessImpact;

 

local.isImpactNull = CirrusLibGeneral.isNullOrUndefined(local.rawImpact);

 

if (local.isImpactNull) {

local.rawImpact = 0;

 

} else {

 

local.rawImpact = CirrusLibMath.toNumber(local.rawImpact);

 

}

 

Repeat this block for all five dropdowns, changing the variable names each time: rawSystems, rawTime, rawCompliance, rawRisk.

 

Remember to click Save after each line of code written.

 

What each function does:

 

data.dd_businessImpact reads the current value of that dropdown. Inside the embedded builder, data. is how you access your own widget values. This is different from field. , which is used to read fields on the parent object page.

 

CirrusLibGeneral.isNullOrUndefined(value) checks whether the value is null or undefined. In plain terms, it asks: has the user selected anything yet? This function returns true if nothing has been selected, and false if a value exists.

 

Why do you need this check?

 

If a user opens the form and changes only one dropdown, the other four have not been answered yet. Their values are null. If you try to run the math on a null value, the calculation breaks entirely. The null check lets you default unanswered questions to 0, so the sum still works correctly as the user works through the form.

 

CirrusLibMath.toNumber(value) converts the dropdown value into an actual number. Even though you configured the option values as 1 and 5, the embedded builder passes them back as strings. "1" and "5" are not numeric values. This is a subtle but critical distinction. If you try to add strings here, it concatenates them instead of summing them. For example, five answers of "1" would give you "11111", not 5. That result passes every threshold check and always shows Critical. Converting with toNumber turns "1" into 1 so the arithmetic works as expected.

 

12_KJ_Screenshot-2026-04-22-170253-1024x577.png

 

Part 2: Sum the Scores

 

Once each dropdown value has been read and converted, this part collects all five numbers and adds them up into a single total score.

 

#Step 2 -- Collect all five numbers and add them up into a single total score.

local.scoreArr = CirrusLibArray.createNewNumericArray();

 

CirrusLibArray.push(local.scoreArr, local.rawImpact);

 

CirrusLibArray.push(local.scoreArr, local.rawSystems);

 

CirrusLibArray.push(local.scoreArr, local.rawTime);

 

CirrusLibArray.push(local.scoreArr, local.rawCompliance);

 

CirrusLibArray.push(local.scoreArr, local.rawRisk);

 

local.getFinalScore = CirrusLibMath.sum(local.scoreArr);

 

 

What each function does:

 

CirrusLibArray.createNewNumericArray() creates a new, empty array that is typed for numbers. You need this because CirrusLibMath.sum only accepts an array as its input. It cannot take individual numbers directly. Think of it like a bag: you cannot hand it five separate items, you have to put them all in the bag first and hand in the bag.

 

13_KJ_Screenshot-2026-04-22-174934.png

 

You can find this information by hovering over the function in the Script Editor.

 

CirrusLibArray.push(array, value) adds a value to the end of an array. You call this once per converted score to load all five values into the array before summing.

 

CirrusLibMath.sum(numbers) takes a numeric array and returns the total of all values in it. The result is stored in local.getFinalScore, which you will use in the next part.

 

14_KJ_Screenshot-2026-04-22-170452.png

 

 

Part 3: Determine the Priority Band

 

Now that we have a total score, this part decides what that score means. It works by setting "Low" as the default and then checking upward through each band, overwriting the result if the score qualifies.

 

#Step 3 -- Sets "Low" as the default and then checks upward through each band, overwriting the result if the score qualifies

local.Result = "Low";

 

local.isMedium = CirrusLibMath.ge(local.getFinalScore, 9);

 

if (local.isMedium) {

 

    local.Result = "Medium";

 

}

 

local.isHigh = CirrusLibMath.ge(local.getFinalScore, 16);

 

if (local.isHigh) {

 

    local.Result = "High";

 

}

 

local.isCritical = CirrusLibMath.ge(local.getFinalScore, 21);

 

if (local.isCritical) {

 

    local.Result = "Critical";

 

}

 

What each function does:

 

CirrusLibMath.ge(number1, number2) means greater than or equal to. It returns true if number1 is greater than or equal to number2. Using strictly greater than (gt) would mean a score of exactly 9 stays Low instead of becoming Medium, because the boundary score would fall through. ge makes sure the boundary is included in the correct band.

 

Why start with "Low" and overwrite upward? You set "Low" as the default first. Each check then overwrites it only if the score qualifies for a higher band. By the end of the three checks, local.Result holds the highest band the score reached. The checks run sequentially rather than as if/else chains, which means a score of 22 passes through all three checks and correctly ends up at Critical.

 

15_KJ_Screenshot-2026-04-22-171141-1024x444.png

 

Part 4: Write the Results to the Output Widgets

 

#Step 4 -- Set the output score to the components

data.priorityScore = local.getFinalScore;

 

data.labelResult = local.Result;

 

The same data. scope you used to read values is used to write them back. Setting data.priorityScore updates the Input Number widget with the total score. Setting data.Result sets the Color Dropdown to the matching option, which is why the option values had to match the values exactly.

 

16_KJ_Screenshot-2026-04-22-172237.png

 

Close the Interactions Editor.

 

Important: Change the OnChange item action for each dropdown to the calculateScore interaction we just finished creating.

 

Save the form.

 

Step 5: Test Before You Link and Save

 

Before saving this form to any Change Request object, test the calculation inside the object page.

 

Open the out of the box Change Request page and create a new instance.

 

From the Approval Checklist selector, change the form to the IT Change Priority Assessment form

 

  • Set all five dropdowns to 1. You should see a score of 5 and a Result of Low
  • Set all five to 5. You should see a score of 25 and a Result of Critical
  • Try a mixed set, for example three 5s and two 1s, and check that the score and band match what you expect

 

(view in My Videos)

 

If everything works as you'd expect, the form is now ready to be used as an object field.

 

Part 2 of this series covers how to wire this form into the Change Request object page so that when a requestor fills it in, the score persists on the record and can drive further behavior, such as auto-populating a Priority field or triggering a workflow.

 

Interaction Functions Used in This Post

 

For reference, here is a summary of every library function used in this tutorial and what it does:

 

Function Library What It Does
isNullOrUndefined(value) CirrusLibGeneral Returns true if the value is null or undefined; false otherwise
toNumber(value) CirrusLibMath Converts a value (such as a string "1") to a numeric data type
createNewNumericArray() CirrusLibArray Creates a new, empty array typed for numeric values
push(array, value) CirrusLibArray Adds a value to the end of an existing array
sum(numbers) CirrusLibMath Returns the sum of all numbers in a numeric array
ge(number1, number2) CirrusLibMath Returns true if number1 is greater than or equal to number2

 

You can download the full interaction and Form used in this post by clicking here.

 

How to Use:

 

  1. Click the file sharing link.
  2. Download files to computer.
  3. Open SAS Model Risk Management > Data Load > Load Priority_Change_Request_Form.zip. This will load the form components and interactions associated with it.

 

Next up: Part 2 - Using the Form in the Change Request Object Page. We will cover how to add the Embedded Builder Page component to the page, load the form, capture the score that the form sends up via triggerParent, and persist it back to a field on the Change Request record.

 

For more information on SAS Model Risk Management, click here.
 

For more articles on SAS Model Risk Management, click here.

 

 

Find more articles from SAS Global Enablement and Learning here.

Contributors
Version history
Last update:
yesterday
Updated by:

Catch up on SAS Innovate 2026

Dive into keynotes, announcements and breakthroughs on demand.

Explore Now →

SAS AI and Machine Learning Courses

The rapid growth of AI technologies is driving an AI skills gap and demand for AI talent. Ready to grow your AI literacy? SAS offers free ways to get started for beginners, business leaders, and analytics professionals of all skill levels. Your future self will thank you.

Get started

Article Tags