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(), andconsole.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
makeRequestcalls