Custom Field with <Select> in Forge UI Kit

Hello Atlassian Developer Community! :slightly_smiling_face:

Disclaimer: I’m very new to both Forge and React.

I have created a Forge App using forge create with the UI Kit template jira-custom-field. When I edit it, I want to use a list to select the item that should be stored. I have been trying to get this to work using <Select /> and it does work - but it looks really bad since the Edit modal only shows the two first items and then there’s a scroll bar that kind of (but not really) works.

Screenshot_2024-06-24_21-48-00

The <Select /> has three items in the screenshot below and it is possible to use the arrow keys as well as some times get the scroll bar to work. But it’s not really something I would like to expose the end users to.

My manifest.yml:

modules:
  jira:customField:
    - key: custom-item
      name: Custom Item
      description: A custom field for Custom Item.
      type: object
      formatter:
        expression: "`[${value.id}] ${value.name}`"
      schema:
        properties:
          id:
            type: string
            searchAlias: ID
          name:
            type: string
            searchAlias: Name
        required: ["id", "name"]
      render: native
      resource: main
      edit:
        resource: edit
        render: native
resources:
  - key: main
    path: src/frontend/index.jsx
  - key: edit
    path: src/frontend/edit.jsx
app:
  runtime:
    name: nodejs18.x
  id: ari:cloud:ecosystem::app/[some-uuid]

My src/frontend/index.jsx:

import React, { useState, useEffect } from "react";
import ForgeReconciler, { Text } from "@forge/react";
import { view } from "@forge/bridge";

const View = () => {
  const [fieldValue, setFieldValue] = useState(null);

  useEffect(() => {
    view.getContext().then((context) => {
      setFieldValue(context.extension.fieldValue);
    });
  }, []);

  if (!fieldValue) {
    return `Empty...`;
  }

  const { id, name } = fieldValue;
  if (!id && !name) {
    return `Empty...`;
  }

  return (
    <>
      <Text>{`[${id}] ${name}`}</Text>
    </>
  );
};

ForgeReconciler.render(
  <React.StrictMode>
    <View />
  </React.StrictMode>
);

My src/frontend/edit.jsx:

import React, { useState, useEffect } from "react";
import ForgeReconciler, {
  Form,
  Label,
  useForm,
  FormSection,
  FormFooter,
  ButtonGroup,
  LoadingButton,
  Button,
  Select,
} from "@forge/react";
import { view } from "@forge/bridge";

const Edit = () => {
  const [renderContext, setRenderContext] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  const { handleSubmit, register, getFieldId, getValues } = useForm();

  useEffect(() => {
    view.getContext().then((context) => {
      setRenderContext(context.extension.renderContext);
    });
  }, []);

  const onSubmit = async (data) => {
    setIsLoading(true);
    try {
      const { item } = data;
      if (!item) {
        throw new Error("Item is required");
      }
      const { value } = item;
      if (!value) {
        throw new Error("Item is required");
      }
      const { id, name } = value;
      if (!id || !name) {
        throw new Error("Item is required");
      }
      await view.submit({ id, name });
    } catch (e) {
      console.error(e);
    } finally {
      setIsLoading(false);
    }
  };

  const items = [
    { id: "ID-001", name: "Foo" },
    { id: "ID-002", name: "Bar" },
    { id: "ID-003", name: "Baz" },
  ];

  const itemOptions = items.map((item) => ({
    label: `[${item.id}] ${item.name}`,
    value: item,
  }));

  return renderContext === "issue-view" ? (
    <Form onSubmit={handleSubmit(onSubmit)}>
      <FormSection>
        <Label labelFor={getFieldId("fieldName")}>Custom field value</Label>
        <Select isSearchable options={itemOptions} {...register("item")} />
      </FormSection>
      <FormFooter>
        <ButtonGroup>
          <Button appearance="subtle" onClick={view.close}>
            Close
          </Button>
          <LoadingButton
            appearance="primary"
            type="submit"
            isLoading={isLoading}
          >
            Submit
          </LoadingButton>
        </ButtonGroup>
      </FormFooter>
    </Form>
  ) : (
    <Form onSubmit={handleSubmit(onSubmit)}>
      <Label labelFor={getFieldId("fieldName")}>Custom field value</Label>
      <Select isSearchable {...register("item")} options={itemOptions} />
    </Form>
  );
};

ForgeReconciler.render(
  <React.StrictMode>
    <Edit />
  </React.StrictMode>
);

Note: items are supposed to be retreived using a resolver, but since the issue is UI related this is a simpler example.

As a reference, creating a new Issue looks just fine:

See reply below for screenshot

I would either like to get the modal to work correctly, or even better to get the <Select /> to work directly in the Issue (where it says Empty... in the screenshot below).

See reply below for screenshot

Any assistance at this point would be greatly appriciated, since I’m not figuring it out. Sorry in advance if this is a really simple fix that I’ve just missed.

1 Like

NOTE: As a new user to the community, I can only upload one screenshot per post.

As a reference, creating a new Issue looks just fine:

1 Like

I would either like to get the modal to work correctly, or even better to get the <Select /> to work directly in the Issue (where it says Empty... in the screenshot below).

1 Like

I found a workaround by using the template jira-custom-field-ui-kit when running forge create (and the category Show All). This seems to be using the UI Kit version 1 (which is or will be deprecated?) - but it works for now.

I have created a repository with code recreating the issue: GitHub - simongottschlag/jira-custom-field-demo: This is a demo project for a jira custom field using Atlassian Forge (UI Kit).

I also recorded setting it up: https://youtu.be/rNh-I7mpXKo?si=SoN2qPLhfChEWiFK

UI Kit v1 is definitively on the path of depreciation; starting a new project using it is, in my opinion, a bad idea.

FYI, the same issue exists also with custom UI: [FRGE-1121] - Ecosystem Jira

And it is sort of a recurring issue with Forge:
https://ecosystem.atlassian.net/browse/FRGE-371
https://ecosystem.atlassian.net/browse/FRGE-1115
https://ecosystem.atlassian.net/browse/FRGE-392

I highly encourage you to create another FRGE ticket to report your case with UI Kit (v2).

We, Forge developers, spend way too much time on this issue.

1 Like