mcpField
U
ui-policies

ui-policies

github.com/happy-technologies-llcDevelopment4141 installsUpdated 2d ago
Repository

About ui-policies

ui-policies is a ServiceNow skill for catalog administrators and developers who build dynamic service catalog forms. It covers conditional field behavior and scripted rules, including the background-script workaround needed to link policy actions to variables.

Key features

  1. 01Create condition-based UI policies
  2. 02Show, hide, require, or disable fields
  3. 03Configure scripted policy conditions
  4. 04Link actions to variables with scripts
  5. 05Test and debug policy behavior

Use cases

  1. 01Show approval fields for selected requests
  2. 02Require justification for high-cost items
  3. 03Make calculated catalog fields read-only
  4. 04Verify conditional form behavior

MCP support

The skill describes using ServiceNow MCP tools such as SN-Create-Record, SN-Update-Record, SN-Query-Table, and SN-Execute-Background-Script to configure and verify UI policies.

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/happy-technologies-llc/happy-platform-skills --skill ui-policies

After installing, type/ui-policiesin Claude Code to confirm it loaded.

Details

From the project README

Catalog UI Policies

Overview

This skill covers creating and managing UI policies for Service Catalog items:

  • Creating UI policies with conditions
  • Show/hide/mandatory/disabled actions
  • Scripted UI policy conditions
  • UI Policy Actions and their REST API limitations
  • Workarounds for linking actions via background scripts
  • Testing and debugging UI policies

When to use: When building dynamic catalog forms that need to show/hide fields, make fields mandatory based on other selections, or implement complex conditional logic.

Who should use this: Catalog administrators and developers building service catalog items with dynamic form behavior.

Prerequisites

  • Roles: catalog_admin or admin
  • Access: catalog_ui_policy, catalog_ui_policy_action, item_option_new tables
  • Knowledge: Basic catalog item structure, variables
  • Related Skills: catalog/variable-management for variable creation

Understanding Catalog UI Policies

UI Policy Components
┌─────────────────────────────────────────────────────────┐
│                    Catalog UI Policy                     │
├─────────────────────────────────────────────────────────┤
│  Catalog Item: [reference to sc_cat_item]               │
│  Short Description: "Show approval fields for >$1000"   │
│  Conditions: amount>1000                                │
│  On Load: true    Reverse If False: true                │
│  Script True: [optional advanced logic]                 │
│  Script False: [optional reverse logic]                 │
├─────────────────────────────────────────────────────────┤
│                    UI Policy Actions                     │
├─────────────────────────────────────────────────────────┤
│  Action 1: manager_approval → visible=true, mandatory=true │
│  Action 2: justification → visible=true                    │
│  Action 3: cost_center → disabled=false                    │
└─────────────────────────────────────────────────────────┘
UI Policy Evaluation
User Opens Form
      │
      ▼
┌─────────────────┐
│  On Load = true?│───No──► Conditions evaluated only on change
      │
     Yes
      │
      ▼
┌─────────────────┐
│ Evaluate        │
│ Conditions      │
└────────┬────────┘
         │
    ┌────┴────┐
    │         │
  True      False
    │         │
    ▼         ▼
┌────────┐ ┌────────────────┐
│ Apply  │ │Reverse If False│───Yes──► Apply opposite actions
│Actions │ │    = true?     │
└────────┘ └───────┬────────┘
                   │
                  No
                   │
                   ▼
              Do nothing

Procedure

Phase 1: Create Basic UI Policy
Step 1.1: Create UI Policy Record

Simple Condition-Based Policy:

Tool: SN-Create-Record
Parameters:
  table_name: catalog_ui_policy
  data:
    catalog_item: [catalog_item_sys_id]
    short_description: "Show approval fields when amount exceeds $1000"
    active: true
    on_load: true
    reverse_if_false: true
    order: 100
    global: false
    run_scripts: false

Result: Returns sys_id of created UI policy (e.g., policy_sys_id)

Step 1.2: Understand UI Policy Fields
FieldTypeDescription
catalog_itemReferenceTarget catalog item
short_descriptionStringPolicy name/description
activeBooleanEnable/disable policy
on_loadBooleanEvaluate when form loads
reverse_if_falseBooleanApply opposite when condition false
orderIntegerExecution order (lower = first)
globalBooleanApply to all catalog items
run_scriptsBooleanEnable Script True/Script False
conditionsConditionsEncoded query against variables
Phase 2: Add UI Policy Conditions
Step 2.1: Simple Field Condition

Conditions compare variable values using encoded query syntax:

Create Policy with Condition:

Tool: SN-Create-Record
Parameters:
  table_name: catalog_ui_policy
  data:
    catalog_item: [catalog_item_sys_id]
    short_description: "Show manager approval for external vendors"
    conditions: "vendor_type=external"
    active: true
    on_load: true
    reverse_if_false: true
    order: 100

Condition Syntax Examples:

ConditionMeaning
priority=1Priority equals 1
amount>1000Amount greater than 1000
category=hardware^urgency=1Category is hardware AND urgency is 1
department=IT^ORdepartment=SecurityDepartment is IT OR Security
requested_for.active=trueReferenced user is active
descriptionISNOTEMPTYDescription has a value
quantityBETWEEN1@10Quantity between 1 and 10
Step 2.2: Multiple Conditions (AND/OR)

AND Conditions:

Tool: SN-Create-Record
Parameters:
  table_name: catalog_ui_policy
  data:
    catalog_item: [catalog_item_sys_id]
    short_description: "Require justification for high-cost IT equipment"
    conditions: "department=IT^hardware_type=laptop^estimated_cost>2000"
    active: true
    on_load: true
    reverse_if_false: true
    order: 200

OR Conditions:

Tool: SN-Create-Record
Parameters:
  table_name: catalog_ui_policy
  data:
    catalog_item: [catalog_item_sys_id]
    short_description: "Show security review for sensitive departments"
    conditions: "department=Finance^ORdepartment=Legal^ORdepartment=HR"
    active: true
    on_load: true
    reverse_if_false: true
    order: 300
Phase 3: Create UI Policy Actions

CRITICAL: UI Policy Actions cannot be fully linked to variables via REST API due to ServiceNow limitations. The catalog_variable field requires special handling.

Step 3.1: Understand the Limitation

When you create a catalog_ui_policy_action via REST API:

  • The record is created successfully
  • The catalog_variable field WILL NOT link properly
  • The action won't work until manually fixed or updated via background script

Why This Happens:

  • The catalog_variable field expects a special format: IO:[variable_sys_id]
  • The REST API doesn't properly resolve this reference type
  • This is a known ServiceNow platform limitation
Step 3.2: Create Action Record (Step 1 of 2)

First, create the UI policy action record:

Tool: SN-Create-Record
Parameters:
  table_name: catalog_ui_policy_action
  data:
    ui_policy: [policy_sys_id]
    visible: true
    mandatory: true
    disabled: false

Result: Returns action sys_id (e.g., action_sys_id)

Note: The action is created but NOT linked to any variable yet.

Step 3.3: Link Action to Variable (Step 2 of 2)

REQUIRED: Use background script to properly link the action:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    // Link UI Policy Action to Catalog Variable
    var actionSysId = '[action_sys_id]';
    var variableSysId = '[variable_sys_id]';

    var gr = new GlideRecord('catalog_ui_policy_action');
    if (gr.get(actionSysId)) {
      // The catalog_variable field requires IO: prefix
      gr.setValue('catalog_variable', 'IO:' + variableSysId);
      gr.update();
      gs.info('Linked UI policy action ' + actionSysId + ' to variable ' + variableSysId);
    } else {
      gs.error('UI policy action not found: ' + actionSysId);
    }
  description: Link UI policy action to catalog variable
Step 3.4: Batch Link Multiple Actions

For multiple actions, batch them in one script:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    // Batch link UI Policy Actions
    var links = [
      { action: '[action1_sys_id]', variable: '[var1_sys_id]' },
      { action: '[action2_sys_id]', variable: '[var2_sys_id]' },
      { action: '[action3_sys_id]', variable: '[var3_sys_id]' }
    ];

    var success = 0;
    var failed = 0;

    links.forEach(function(link) {
      var gr = new GlideRecord('catalog_ui_policy_action');
      if (gr.get(link.action)) {
        gr.setValue('catalog_variable', 'IO:' + link.variable);
        gr.update();
        gs.info('Linked: ' + link.action + ' -> ' + link.variable);
        success++;
      } else {
        gs.error('Action not found: ' + link.action);
        failed++;
      }
    });

    gs.info('Batch link complete: ' + success + ' success, ' + failed + ' failed');
  description: Batch link UI policy actions to variables
Phase 4: UI Policy Action Types
Step 4.1: Show/Hide Variables

Show a variable when condition is true:

Tool: SN-Create-Record
Parameters:
  table_name: catalog_ui_policy_action
  data:
    ui_policy: [policy_sys_id]
    visible: true
    mandatory: false
    disabled: false

Then link to variable using background script (Step 3.3).

Hide a variable (with reverse_if_false):

  • Set visible: true in action
  • Set reverse_if_false: true on policy
  • When condition is FALSE, variable will be hidden
Step 4.2: Mandatory Actions

Make variable mandatory when condition is true:

Tool: SN-Create-Record
Parameters:
  table_name: catalog_ui_policy_action
  data:
    ui_policy: [policy_sys_id]
    visible: true
    mandatory: true
    disabled: false

Common Pattern: Show AND make mandatory:

  • visible: true - Show the field
  • mandatory: true - Require a value
  • With reverse_if_false: true - When condition false, field hidden and not required
Step 4.3: Disabled/Read-Only Actions

Make variable read-only when condition is true:

Tool: SN-Create-Record
Parameters:
  table_name: catalog_ui_policy_action
  data:
    ui_policy: [policy_sys_id]
    visible: true
    mandatory: false
    disabled: true

Use Case: Lock calculated fields or display-only values.

Phase 5: Scripted UI Policies
Step 5.1: Enable Script Execution

For complex conditions that can't be expressed in simple encoded queries:

Tool: SN-Update-Record
Parameters:
  table_name: catalog_ui_policy
  sys_id: [policy_sys_id]
  data:
    run_scripts: true
    script_true: |
      // Runs when condition is TRUE
      // Access variables via g_form
      var amount = g_form.getValue('amount');
      var dept = g_form.getValue('department');

      if (parseFloat(amount) > 5000 && dept == 'IT') {
        // Additional client-side logic
        g_form.showFieldMsg('amount', 'Requires CIO approval', 'info');
      }
    script_false: |
      // Runs when condition is FALSE (optional)
      g_form.hideFieldMsg('amount');
Step 5.2: Script Examples

Complex Validation:

// script_true
var hardware = g_form.getValue('hardware_type');
var quantity = parseInt(g_form.getValue('quantity')) || 0;

// Show warning for bulk orders
if (hardware == 'laptop' && quantity > 10) {
  g_form.showFieldMsg('quantity', 'Bulk orders require procurement approval', 'warning');
}

// Dynamic mandatory based on multiple fields
if (hardware == 'other') {
  g_form.setMandatory('other_description', true);
}

Date Validation:

// script_true
var startDate = g_form.getValue('start_date');
var endDate = g_form.getValue('end_date');

if (startDate && endDate) {
  var start = new Date(startDate);
  var end = new Date(endDate);

  if (end < start) {
    g_form.showFieldMsg('end_date', 'End date must be after start date', 'error');
    g_form.setMandatory('end_date', true);
  }
}
Phase 6: Complete UI Policy Example
Step 6.1: Full Implementation

Scenario: Software request form where:

  • If license type is "Enterprise", show cost center and manager approval
  • If quantity > 5, require business justification

Step 1: Get variable sys_ids:

Tool: SN-Query-Table
Parameters:
  table_name: item_option_new
  query: cat_item=[catalog_item_sys_id]
  fields: sys_id,name,question_text
  limit: 50

Step 2: Create Policy 1 - Enterprise License:

Tool: SN-Create-Record
Parameters:
  table_name: catalog_ui_policy
  data:
    catalog_item: [catalog_item_sys_id]
    short_description: "Show approval fields for Enterprise license"
    conditions: "license_type=enterprise"
    active: true
    on_load: true
    reverse_if_false: true
    order: 100
# Result: policy1_sys_id

Step 3: Create Actions for Policy 1:

Tool: SN-Create-Record
Parameters:
  table_name: catalog_ui_policy_action
  data:
    ui_policy: [policy1_sys_id]
    visible: true
    mandatory: true
    disabled: false
# Result: action1a_sys_id (for cost_center)
Tool: SN-Create-Record
Parameters:
  table_name: catalog_ui_policy_action
  data:
    ui_policy: [policy1_sys_id]
    visible: true
    mandatory: true
    disabled: false
# Result: action1b_sys_id (for manager_approval)

Step 4: Link Actions to Variables:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var links = [
      { action: '[action1a_sys_id]', variable: '[cost_center_var_sys_id]' },
      { action: '[action1b_sys_id]', variable: '[manager_approval_var_sys_id]' }
    ];

    links.forEach(function(link) {
      var gr = new GlideRecord('catalog_ui_policy_action');
      if (gr.get(link.action)) {
        gr.setValue('catalog_variable', 'IO:' + link.variable);
        gr.update();
        gs.info('Linked: ' + gr.sys_id);
      }
    });
  description: Link enterprise license policy actions

Step 5: Create Policy 2 - Bulk Order:

Tool: SN-Create-Record
Parameters:
  table_name: catalog_ui_policy
  data:
    catalog_item: [catalog_item_sys_id]
    short_description: "Require justification for bulk orders (>5)"
    conditions: "quantity>5"
    active: true
    on_load: true
    reverse_if_false: true
    order: 200
# Result: policy2_sys_id

Step 6: Create and Link Action for Policy 2:

Tool: SN-Create-Record
Parameters:
  table_name: catalog_ui_policy_action
  data:
    ui_policy: [policy2_sys_id]
    visible: true
    mandatory: true
    disabled: false
# Result: action2_sys_id
Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var gr = new GlideRecord('catalog_ui_policy_action');
    if (gr.get('[action2_sys_id]')) {
      gr.setValue('catalog_variable', 'IO:[justification_var_sys_id]');
      gr.update();
      gs.info('Linked bulk order justification action');
    }
  description: Link bulk order policy action
Phase 7: Testing and Debugging
Step 7.1: Verify UI Policy Configuration

Query all policies for a catalog item:

Tool: SN-Query-Table
Parameters:
  table_name: catalog_ui_policy
  query: catalog_item=[catalog_item_sys_id]^active=true
  fields: sys_id,short_description,conditions,on_load,reverse_if_false,order,run_scripts
  limit: 50

Query all actions for a policy:

Tool: SN-Query-Table
Parameters:
  table_name: catalog_ui_policy_action
  query: ui_policy=[policy_sys_id]
  fields: sys_id,catalog_variable,visible,mandatory,disabled
  limit: 20
Step 7.2: Debug Action Links

Check if catalog_variable is properly linked:

Tool: SN-Query-Table
Parameters:
  table_name: catalog_ui_policy_action
  query: ui_policy=[policy_sys_id]
  fields: sys_id,catalog_variable.name,visible,mandatory,disabled
  limit: 20

If catalog_variable.name is empty, the link failed - run the background script again.

Step 7.3: Testing Checklist

Before Testing:

  • All UI policies are active
  • All policy actions have linked variables (catalog_variable not empty)
  • Order numbers are set correctly (no conflicts)
  • reverse_if_false is set appropriately

Test Scenarios:

  1. On Load: Open form fresh - verify initial visibility
  2. True Condition: Set values to make condition true - verify actions apply
  3. False Condition: Change values to make condition false - verify reverse
  4. Multiple Policies: Test combinations of conditions
  5. Script Policies: Verify scripts execute without errors
Step 7.4: Common Debug Commands

Find unlinked actions:

Tool: SN-Query-Table
Parameters:
  table_name: catalog_ui_policy_action
  query: ui_policy.catalog_item=[catalog_item_sys_id]^catalog_variableISEMPTY
  fields: sys_id,ui_policy.short_description
  limit: 50

Get variable sys_ids by name:

Tool: SN-Query-Table
Parameters:
  table_name: item_option_new
  query: cat_item=[catalog_item_sys_id]^name=manager_approval
  fields: sys_id,name

Tool Usage Summary

OperationMCP ToolNotes
Create UI PolicySN-Create-Recordcatalog_ui_policy table
Create UI Policy ActionSN-Create-Recordcatalog_ui_policy_action table
Link Action to VariableSN-Execute-Background-ScriptREQUIRED - REST API limitation
Query PoliciesSN-Query-Tablecatalog_ui_policy
Query ActionsSN-Query-Tablecatalog_ui_policy_action
Update PolicySN-Update-RecordFor script_true/script_false

Best Practices

  • Descriptive Names: Use clear short_description for debugging
  • Order Carefully: Lower order executes first - avoid conflicts
  • Use reverse_if_false: Cleaner than creating two opposing policies
  • Test Both States: Always test true AND false conditions
  • Minimize Scripts: Use conditions when possible - scripts are slower
  • Document Logic: Comment complex conditions in description field
  • Batch Link Actions: Use single background script for multiple links
  • Verify Links: Always query to confirm catalog_variable is populated

Troubleshooting

UI Policy Not Executing

Symptom: Variable visibility/mandatory doesn't change Causes:

  1. Policy inactive
  2. Condition syntax error
  3. Action not linked to variable Solution:
Tool: SN-Query-Table
Parameters:
  table_name: catalog_ui_policy
  query: catalog_item=[item_sys_id]
  fields: short_description,active,conditions

Check active=true and verify condition syntax.

Action Not Linked (catalog_variable Empty)

Symptom: Policy executes but field doesn't change Cause: REST API limitation - action not properly linked Solution:

Tool: SN-Execute-Background-Script
Parameters:
  script: |
    var gr = new GlideRecord('catalog_ui_policy_action');
    gr.get('[action_sys_id]');
    gr.setValue('catalog_variable', 'IO:[variable_sys_id]');
    gr.update();
    gs.info('Fixed action link');
  description: Fix unlinked UI policy action
reverse_if_false Not Working

Symptom: Variable stays visible/mandatory when condition is false Causes:

  1. reverse_if_false not enabled
  2. on_load not enabled (only evaluates on change) Solution:
Tool: SN-Update-Record
Parameters:
  table_name: catalog_ui_policy
  sys_id: [policy_sys_id]
  data:
    on_load: true
    reverse_if_false: true
Script Errors

Symptom: Console errors when form loads, script not executing Cause: JavaScript syntax error in script_true or script_false Solution:

  1. Check browser console for errors
  2. Validate JavaScript syntax
  3. Test script in browser console first
Multiple Policies Conflicting

Symptom: Unpredictable variable behavior Cause: Multiple policies affecting same variable with conflicting actions Solution:

  1. Query all policies affecting the variable
  2. Adjust order numbers
  3. Consider consolidating into single policy with complex condition

Related Skills

  • catalog/variable-management - Create and configure variables
  • catalog/item-creation - Full catalog item setup
  • catalog/approval-workflows - Approval configuration
  • admin/script-execution - Background script patterns

References

Comments

Markdown supported