Select Lists with Other

Make a field writable only if a certain value is set in another field

Imagine a scenario where you want to get the user’s favourite fruit:

The problem here is that our select list options probably don’t contain the names of all fruits, and there will always be a difficult person who wants something not on the list. What we’ll do is have an option Other, which if selected, will make a free text field appear.

Or more realistically, this field could be the names of your Customers, and you might want to allow people to add additional ones.

We’ll create a text field called Favourite Fruit (Other), which only becomes visible if the Other select list option is chosen. The, code to apply to the Favourite Fruit field, is:

def otherFaveField = getFieldByName("Favourite Fruit (Other)")
def faveFruitField = getFieldById(getFieldChanged())

def selectedOption = faveFruitField.getValue() as String
def isOtherSelected = selectedOption == "Other"

otherFaveField.setHidden(!isOtherSelected)
otherFaveField.setRequired(isOtherSelected)

And the result:

The behaviour is attached to the field to which we want to list for changes, in this case Favourite Fruit, and not the Favourite Fruit (Other) field.

This example makes use of getFieldChanged(), which always returns the field ID of the field the behaviour fires for.

We can do a little bit more here for bonus points…​ we would like to create an Option with the other value, then update the issue to have this new option, and remove the value from the other field. To do this we use a listener on the Issue Updated event with the following code:

import com.atlassian.jira.component.ComponentAccessor

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def optionsManager = ComponentAccessor.getOptionsManager()
def faveFruitOtherFld = customFieldManager.getCustomFieldObjectByName("Favourite Fruit (Other)")
def issueService = ComponentAccessor.getIssueService()

def issue = event.issue
def otherFaveFruit = issue.getCustomFieldValue(faveFruitOtherFld) as String
if (otherFaveFruit) {
    def faveFruitFld = customFieldManager.getCustomFieldObjectByName("Favourite Fruit")

    def fieldConfig = faveFruitFld.getRelevantConfig(issue)
    def currentOptions = optionsManager.getOptions(fieldConfig)
    def newSeqId = currentOptions*.sequence.max() - 1
    def option = optionsManager.createOption(fieldConfig, null, newSeqId, otherFaveFruit)

    def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
    def issueInputParameters = issueService.newIssueInputParameters()
    issueInputParameters.with {
        addCustomFieldValue(faveFruitFld.idAsLong, option.optionId.toString())
        addCustomFieldValue(faveFruitOtherFld.idAsLong, null)
    }
    def updateValidationResult = issueService.validateUpdate(currentUser, issue.id, issueInputParameters)
    if (updateValidationResult.isValid()) {
        issueService.update(currentUser, updateValidationResult)
    } else {
        log.warn("Failed to update issue: ${issue.key}: ${updateValidationResult.errorCollection}")
    }
}

This script is just a starting point - you may want to check that the user-provided other value doesn’t actually already exist in the list.

As we used the custom field name in two different scripts it’s a good idea to extract it to some common class of constants, so you only need modify it in one place if you change the field display name.