How to save and track time in Jira Software? Watch our joint webinar with Tempo!

Dynamic Forms for Jira

Jira Server
Last updated Oct 30, 2019

Use data from Bundled Fields in Script Runner

This page provides information on using saved data in the Script Runner app.

Dynamic Froms app allows to use data from Bundled Fields in the Script Runner, or in the external app.

The following .JSON file shows all field types available in Bundled Fields.

    "baseGroupId": {
        "fields": [
                "id": "1a66be6f-b9a6-4bb0-9780-7113f53e4ce6", 
                "name": "text fields", 
                "type": "text", 
                "required": true, 
                "showLabel": true, 
                "options": [], 
                "value": "test" 
                "id": "df42c0c8-0f36-4a6f-b7c9-1030d12e8621",
                "name": "select field",
                "type": "select",
                "required": true,
                "showLabel": true,
                "options": [
                    { "id": "48c432d0-93f2-46c9-959a-b19d56715b8f", "name": "option 1" },
                    { "id": "c891fc2c-2827-437f-81d2-d47ea8da4d29", "name": "option 2" },
                    { "id": "eb9ca7fc-ede1-47c8-9a3c-63823e9e1194", "name": "option 3" }
                "value": "c891fc2c-2827-437f-81d2-d47ea8da4d29"
                "id": "8655d759-d16a-4d54-b414-bb9391b42c2e",
                "name": "checkbox",
                "type": "checkbox",
                "required": true,
                "showLabel": true,
                "options": [
                    { "id": "1ae64d17-815b-4667-b26d-b1855ead1673", "name": "check 1" },
                    { "id": "ff303f03-f7b7-44fc-81fd-d0329d7deaaa", "name": "check 2" },
                    { "id": "9b2d710d-0505-46b4-b35f-95c1b3d211a3", "name": "check 3" }
                "value": "1ae64d17-815b-4667-b26d-b1855ead1673,ff303f03-f7b7-44fc-81fd-d0329d7deaaa"
                "id": "79f1c607-8afe-489a-81f4-a13cba9b499e", 
                "name": "multitext field", 
                "type": "textarea", 
                "required": true, 
                "showLabel": true, 
                "options": [], 
                "value": "test multitext" 
                "id": "1e1a5b39-c0c8-4426-8b40-33a7a99dacfc", 
                "name": "date field", 
                "type": "date", 
                "required": true, 
                "showLabel": true, 
                "options": [], 
                "value": "2018-11-20" 
    "id": "baseGroupId"

Get Bundled Field’s value

Variable (String) Description Example
issueKey Key of issue where bundled field is placed WORK-27
bundledFieldId ID of source bundled field customfield_10300
fieldName Name of the field in column in bundled field select field
Integer row Number of row in bundled field 0
Rows numbering starts from 0.

The following example shows how to get Bundled Field’s value.

import com.atlassian.jira.component.ComponentAccessor
import groovy.json.JsonSlurper
import org.apache.log4j.Logger
import org.apache.log4j.Level

def log = Logger.getLogger("com.onresolve.scriptrunner.runner.ScriptRunnerImpl")

//key of issue, where the bundledfields value is
String issueKey = 'WORK-27'
//id of bundledfield where we are looking for value
String bundledFieldId= "customfield_10300" 
//field column in bundledfield
String fieldName = "select field"
//row in bundledfield
Integer row = 0 

def issueManager = ComponentAccessor.getIssueManager()
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def cfBundledFields = customFieldManager.getCustomFieldObject(bundledFieldId)
def issue = issueManager.getIssueObject(issueKey)

String cfValue = issue.getCustomFieldValue(cfBundledFields)
Object jsonValue = new JsonSlurper().parseText(cfValue)

////Retrieve a value of requested row and field name
List fields = getFieldsForRow(row,(Map) jsonValue)
Map field = getFieldByName(fieldName,fields)
def value = getFieldValue(field)"my subField ${fieldName} value is ${value}")

def String getFieldValue(Map field){
    def type = field.type
    if(type == 'select' || type == 'checkbox'){
        return getOptionValue(field)
    return field.value

def String getOptionValue(Map field) {
    List<Map> allOptions = (List<Map>) field.options
    String val = field.value
    String[] selectedIds = val.split(',')
    List<Map> selectedOptions = allOptions.findAll { in selectedIds }
    return', ')

def Map getFieldByName(fieldName, List<Map> fields){
    return fields.find{ == fieldName}

def List getFieldsForRow(row,Map json){
    List fields = null
    int i=0
    json.each{k,v -> 
        if(i == row){
            fields = ((Map) v).get("fields")
    return fields

Copy Bundled Field’s value

Variable (String) Description Example
issueFromKey Key of issue from which field’s value will be copied WORK-27
issueToKey Key of issue to which field’s value will be copied WORK-28
cfFromId ID of source custom field customfield_10300
cfToId ID of target custom field customfield_10403

The following example shows how to copy Bundled Field’s value to another field with the same configuration.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.ModifiedValue

String issueFromKey = 'WORK-27'
String issueToKey = 'WORK-28'
String cfFromId = "customfield_10300" //bundledfield id copy from
String cfToId = "customfield_10403" //bundledfield id copy to(copy to field must have the same configuration)

def issueManager = ComponentAccessor.getIssueManager()
def issueFrom = issueManager.getIssueObject(issueFromKey)
def issueTo = issueManager.getIssueObject(issueToKey)

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def cfFrom = customFieldManager.getCustomFieldObject(cfFromId)
def cfTo = customFieldManager.getCustomFieldObject(cfToId)

def cfValueFrom = issueFrom.getCustomFieldValue(cfFrom)
def cfValueTo = issueTo.getCustomFieldValue(cfTo)

if (cfFrom && cfTo) {
    def changeHolder = new DefaultIssueChangeHolder()
    cfTo.updateValue(null, issueTo, new ModifiedValue(cfValueTo, cfValueFrom),changeHolder)

issueTo.getCustomFieldValue(cfTo) != null