Behaviours

Behaviours dynamically control how fields appear and behave on issue create, edit, and transition screens. Using JavaScript scripts, you can show/hide fields, make them required, set default values, change field descriptions, and react to user input — all in real-time as the user interacts with the form.

Architecture

Behaviours use Jira's UI Modifications (UIM) mechanism — a Forge-native system for modifying issue forms without page reloads.

[User opens form] → [ScriptForge filters matching behaviours] 
    → [onInit script runs] → [Fields modified]

[User changes a field] → [onChange script runs] → [Fields modified]

The system has two components:

  • UIM Client — Runs in the browser, intercepts form events, applies field modifications
  • Forge Data Provider — Backend that stores behaviour configurations and provides the script to execute

Lifecycle Events

Each behaviour script has two entry points:

onInit

Runs when the form first opens. Use it to set up initial field states — defaults, visibility, required status.

onChange

Runs when a user changes a field value. Use it to react dynamically — cascade values, show/hide related fields, validate input.

Scope Configuration

Each behaviour is scoped to:

Scope Options
Projects Specific projects, or "All"
Work Types Specific issue types, or "All"
View Create, View/Edit, or Transition screen

Limitation: You cannot use "All Projects" AND "All Work Types" simultaneously. At least one must be specific.

Fields API — Writing (Modifying Fields)

These methods modify how fields appear on the form:

Method Effect
field.setRequired(true/false) Make a field mandatory or optional
field.setVisible(true/false) Show or hide a field entirely
field.setDescription('text') Change the help text below the field
field.setName('New Label') Change the field's display label
field.setValue(value) Set or change the field's value
field.setDefault(value) Set the initial default value (onCreate only)
field.setReadOnly(true/false) Make a field non-editable
field.setOptionsVisibility(map) Show/hide specific options in a dropdown

setOptionsVisibility Example

// Only show "Critical" and "High" options in the Priority dropdown
fields.priority.setOptionsVisibility({
  'Critical': true,
  'High': true,
  'Medium': false,
  'Low': false,
  'Lowest': false
});

Fields API — Reading

Method Returns
fields.getFieldById('customfield_10001') Get a field reference by ID
field.getValue() Current value of the field
field.getName() Current display name
field.isRequired() Whether it's currently required
field.isVisible() Whether it's currently visible
field.isReadOnly() Whether it's currently read-only

Context Object

Your script has access to a context object:

Property Description
context.projectKey The project this form is in
context.issueType The issue type being created/edited
context.change (onChange only) Which field changed and its new value
context.fields Direct access to all fields on the form

View Detection

if (isCreateView()) { /* form is creating a new issue */ }
if (isEditView())   { /* form is editing an existing issue */ }
if (isTransitionView()) { /* form is for a workflow transition */ }

Real-World Examples

Example 1: Make "Due Date" required for Bugs

// onInit
if (context.issueType === 'Bug') {
  fields.dueDate.setRequired(true);
  fields.dueDate.setDescription('Required for all bugs — enter the target fix date');
}

Example 2: Hide fields based on priority

// onInit + onChange
const priority = fields.priority.getValue();

if (priority === 'Low' || priority === 'Lowest') {
  fields.getFieldById('customfield_10050').setVisible(false); // Hide "Escalation Contact"
} else {
  fields.getFieldById('customfield_10050').setVisible(true);
}

Example 3: React to priority changes (onChange)

// onChange
if (context.change.field === 'priority') {
  const newPriority = context.change.value;
  
  if (newPriority === 'Critical') {
    fields.assignee.setRequired(true);
    fields.dueDate.setRequired(true);
    fields.dueDate.setDescription('Critical issues must have a due date within 48 hours');
  } else {
    fields.assignee.setRequired(false);
    fields.dueDate.setRequired(false);
    fields.dueDate.setDescription('');
  }
}

Example 4: Cascading dropdown visibility

// onChange — show different components based on the selected category
if (context.change.field === 'customfield_10001') { // Category
  const category = context.change.value;
  
  if (category === 'Frontend') {
    fields.components.setOptionsVisibility({
      'React': true, 'Angular': true, 'Vue': true,
      'Spring': false, 'Django': false, 'Node.js': false
    });
  } else if (category === 'Backend') {
    fields.components.setOptionsVisibility({
      'React': false, 'Angular': false, 'Vue': false,
      'Spring': true, 'Django': true, 'Node.js': true
    });
  }
}

Example 5: Read-only fields on transitions

// onInit — lock fields during the "Release" transition
if (isTransitionView()) {
  fields.summary.setReadOnly(true);
  fields.priority.setReadOnly(true);
  fields.getFieldById('customfield_10020').setReadOnly(true); // Story Points
}

Example 6: Default values on create

// onInit — set defaults for new issues
if (isCreateView()) {
  fields.priority.setDefault('Medium');
  fields.getFieldById('customfield_10030').setDefault('Unplanned');
}

Example 7: Call external data with makeRequest

// onInit — fetch team assignment from an external API
const response = await makeRequest('/rest/api/3/project/' + context.projectKey);
const projectLead = response.body.lead.accountId;

fields.assignee.setDefault(projectLead);
fields.assignee.setDescription('Auto-assigned to project lead');

Supported Field Types

Behaviours work with most Jira field types on the create, view/edit, and transition screens. The exact set of supported operations varies by view and field type — for example, setValue works on text fields across all views, but setOptionsVisibility only applies to select/dropdown fields.

Common supported fields: Summary, Description, Priority, Assignee, Labels, Components, Fix Versions, Due Date, Story Points, and any custom fields of type text, number, select, multi-select, or date.

Logging and Debugging

  • Use console.log(), console.warn(), and console.error() in your behaviour scripts
  • Check Execution History for behaviour execution logs
  • Use the browser's developer console to see UIM client-side errors
  • Behaviours execute quickly (sub-second) — if you see lag, check for heavy makeRequest calls