How to dynamically add controls with Forge?

According to the custom field type document:
https://developer.atlassian.com/platform/forge/manifest-reference/modules/jira-custom-field-type/#example

You can have a custom field type with type = string and collection = list.

But then how do you handle the edit interface? How can you dynamically add input fields for the up to 100 values?

I want to have a button to add/remove input fields via onClick handler, but I cannot find how to implement it. JQuery seems to be out (it complains there’s no document element).

Found the answer. There are two ways to do custom fields in Jira Cloud, Custom UI and UI Kit. UI Kit is for simpler things and do not support dynamically adding/removing controls. Custom UI is the way to go for that, and you use ReactJS to create the UI (choose Custom UI during forge create for a starting example).

2 Likes

Some additional notes.

The sample code generated by forge create uses @atlaskit for form construction.

For the form itself, it uses Form which contains the properties formProps, dirty and submitting.
For each input field, it uses a Field that encapsulates other controls like TextField.

The way Field and TextField are designed, I found that I cannot specify my own id or key attribute. Field provides a name attribute that is passed down to TextField.

The result is for all the dynamically added rows, the TextField will all point to the same state variable, so they will all share the same value.

If I remove Field and use TextField directly, it will work, but the Form’s dirty flag will remain false even after editing the values.

The workaround is to give each Field a unique name, e.g. Name1, Name2, …, instead of expecting a single Name with an array of values. Then handle that accordingly in onSubmit().

Another issue is the dirty property of the Form. I have to add another state variable, default to false and set to true if rows are added/removed, then enable/disable the submit button based on that along with dirty and submitting.

Yet another issue is onChange event. ReactJS allows either using defaultValue, or value + onChange. If I need to do something on change, I can only use the later option. In the onChange handler I must update the state, but that messes with how Form handles the dirty flag, if the state is updated by onChange, dirty will be false. So as a workaround I have to use my own state variable (turn it on in onChange), but that means losing the ability to disable submit if the fields have been reverted to original values.