Scripted Fields

Scripted Fields are custom fields whose values are computed by a script rather than entered manually. They run a JavaScript calculation whenever the field is rendered and display the result on the issue view.

How Scripted Fields Work

  1. You create a Scripted Field with a script that computes a value
  2. The field appears on issues just like any other custom field
  3. When an issue is viewed, ScriptForge runs your script and renders the result
  4. The computed value is displayed (as text, number, or paragraph)

Field Types

ScriptForge supports three custom field types:

Type Output Use Case
String Single line of text Status labels, computed names, concatenations
Number Numeric value Calculations, counts, scores
Paragraph Multi-line text / rich content Summaries, generated reports, formatted data

Creating a Scripted Field

  1. Navigate to Apps → ScriptForge → Scripted Fields
  2. Click Create Scripted Field
  3. Configure:
    • Name: The field label shown on issues
    • Description: What this field calculates
    • Type: String, Number, or Paragraph
    • Script: JavaScript that returns the computed value
  4. Click Save

After creation, add the field to your issue screens through Jira's field configuration (just like any custom field).

Script Context

Your script has access to the current issue's data and the full HAPI library:

// 'issue' context provides the current issue key
const issue = await WorkItems.getByKey(context.issueKey);

Real-World Examples

Calculate days since creation

const issue = await WorkItems.getByKey(context.issueKey);
const created = new Date(issue.created);
const now = new Date();
const days = Math.floor((now - created) / (1000 * 60 * 60 * 24));
return days;

Type: Number

Count sub-tasks

const issue = await WorkItems.getByKey(context.issueKey);
const subtasks = await issue.getSubTaskObjects();
return subtasks.length;

Type: Number

Show completion percentage

const issue = await WorkItems.getByKey(context.issueKey);
const subtasks = await issue.getSubTaskObjects();

if (subtasks.length === 0) return 'No sub-tasks';

const done = subtasks.filter(s => s.status === 'Done').length;
const pct = Math.round((done / subtasks.length) * 100);
return `${pct}% (${done}/${subtasks.length})`;

Type: String

Generate a risk label based on multiple factors

const issue = await WorkItems.getByKey(context.issueKey);
const priority = issue.priority;
const dueDate = issue.dueDate ? new Date(issue.dueDate) : null;
const now = new Date();

let risk = 'Low';

if (priority === 'Critical' || priority === 'High') {
  risk = 'Medium';
}
if (dueDate && dueDate < now) {
  risk = 'High';
}
if (priority === 'Critical' && dueDate && dueDate < now) {
  risk = 'Critical';
}

return risk;

Type: String

Performance

  • Scripted fields execute each time the issue is rendered (viewing the issue, appearing in a list, etc.)
  • Keep scripts fast — avoid complex JQL searches or multiple API calls
  • Results are not cached between views; the script runs fresh each time
  • Heavy calculations should consider using Entity Properties (written by a listener) and reading the stored value instead