Read and Write TGNG data (Table Grid Next Generation)

jeff singler October 1, 2020


I am attempting to read contents of a table grid next generation custom field from a current issue and copy it's contents to the same table grid field in a create new issue form.  Unsure how this gets done, the challenge here seems to be targeting a new form to write the grid data.  Here is some dirty code we have been playing with.


import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.user.ApplicationUser;
import com.atlassian.plugin.PluginAccessor;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.IssueManager;
import com.idalko.tgng.jira.server.api.*
import static com.atlassian.jira.issue.IssueFieldConstants.*;

IssueManager issueManager = ComponentAccessor.getOSGiComponentInstanceOfType(IssueManager.class)
//Issue issue = issueManager.getIssueObject(issue.key); //actual use
//Long issueId = issue.getId()
CustomFieldManager customFieldManager = ComponentAccessor.getOSGiComponentInstanceOfType(CustomFieldManager.class);

if (getBehaviourContextId() == "SPR") {

def contextIssue = issueManager.getIssueObject(getContextIssueId())
def contextIssueId = contextIssue.getId()

//Get Company Value ....................
def CompanyCF = customFieldManager.getCustomFieldObject("customfield_11002")//Company
def contextCompanyCF = contextIssue.getCustomFieldValue(CompanyCF) as String
def CompanyCFconfig = CompanyCF.getRelevantConfig(contextIssue)
def optionsManager = ComponentAccessor.getOptionsManager()
def options1 = optionsManager.getOptions(CompanyCFconfig)
def optionToSelect = options1.find { it.value == contextCompanyCF }
//Get Items grid.......................................
// Get TGNG custom field id
CustomField tgngCustomField = customFieldManager.getCustomFieldObjectsByName("Items")[0]
Long tgngCustomFieldId = tgngCustomField.getIdAsLong()
ApplicationUser user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
PluginAccessor pluginAccessor = ComponentAccessor.getPluginAccessor()
Class apiServiceClass = pluginAccessor.getClassLoader().loadClass("com.idalko.tgng.jira.server.api.GridService")
def gridService = ComponentAccessor.getOSGiComponentInstanceOfType(apiServiceClass)

// Read field data
def fieldData = gridService.readFieldData(contextIssueId, tgngCustomFieldId, user, null)
def gridRows = fieldData.getRows()
//def fieldData2 = ""

/*StringBuilder result = new StringBuilder()
for (row in gridRows) {
def columns = row.getColumns()
result.append("Qty: ${columns.get("qty")}, ")
result.append("Item#/Description: ${columns.get("vendoritemnumber")}, ")
result.append("GL Account: ${columns.get("glaccountno")}, ")
result.append("UoM: ${columns.get("uom")}; ")
result.append("Unit Price: ${columns.get("unitprice")};<br>")*/

//fieldData2 = gridService.addRows(null, tgngCustomFieldId, user, [
//["qty": "2", "vendoritemnumber": "123456", "glaccountno": "654321", "uom": "Each", "unitprice": "2.50"]

//Write Form Values..........
getFieldById("issuelinks-linktype").setFormValue("Creates").setReadOnly(true)//link Type


1 answer

0 votes
Adrienne Bolger October 13, 2020

It's unclear here what you are trying to do. Are you trying to:

(1) use code to completely create and save a new issue with your copied grid data? (Example: closing out or changing workflow state in Issue A creates a second Issue B)  

OR are you trying to: 

(2) Make it so that when the Create New Issue screen pops up, the data in the Grid is always a specific value from some other issue? 


If it's (1), to me it looks like what you are missing is a reference to your new issue? If you are using Script Runner to run this code, "issue" is a special variable only available on certain Script Runner hooks (See 

TGNG fields are just custom fields, however. So I think what you need can be done by modifying the answer from this question:


If it's (2), then you can use the plugin itself for that: the plugin for each grid lets you set Default values for showing on the screen:

jeff singler October 14, 2020

More like number 2.  From a create new form window, I need the values from the table grid in the context of the issue already open to populate into the table grid on the new issue form.  Or more accurately we need to copy values from the original grid into the new grid.  Trouble is I seem to be needing to target an issue to do that but there is none existing yet as it is a new form window.

Adrienne Bolger October 15, 2020

Where is the context coming from in your case? There are multiple example in this forum of script runner scripts for "cloning" an issue, rather than just clicking the "create issue" button in JIRA, that might be closer to what you want. (Here is a Service desk example from the documentation: 

Alternately if this is from a custom post function or workflow action you have added, I believe it is possible to get your contextual issue from specific reserved keywords from script runner (e.g. "event.issue" is available for all issue update events, etc.)


Script Runner also has the concept of an "initialiser" function:

Which is what Adaptavist recommends for setting field defaults on create. It looks like initializers offer a default 'issueContext' variable which might contain what you want if someone has clicked on a custom 'Clone this Issue' type action rather than the generic 'Create' button from a top level menu.

jeff singler October 15, 2020

the view we were using was actually a script fragment for creating a constrained issue so we can have it show up in a specific spot.  Then from there it would copy data fields from the current issue into the fields on the form pop up.  We used a behavior to accomplish this but we are stuck with the table grid field.  we can get other fields to come in but just not the table grid values.  

Suggest an answer

Log in or Sign up to answer