Implementing Search Functionality in a Forge UI Kit Macro for Confluence

Hello Atlassian Developer Community,

I am working on a Confluence macro using the Forge UI Kit. The purpose of this macro is to display a list of Jira issues and offer search functionality so that users can filter the displayed issues based on their search query.

Here’s the working code I have:

import ForgeUI, { render, Macro, Fragment, Text, useState, Table, Head, Row, Cell, Button, Link } from '@forge/ui';
import api, { route } from "@forge/api";

const handleSearch = async () => {
    const response = await api.asUser().requestJira(route`/rest/api/3/search?jql=project=TD`);
    const data = await response.json();
    return data.issues || [];
};
const JiraMacro = () => {
    const [issues, setIssues] = useState(async () => await handleSearch());

    const refreshIssues = async () => {
        const updatedIssues = await handleSearch();
        setIssues(updatedIssues);
    };

    if (!issues.length) {
        return <Text>No issues found.</Text>;
    }

    return (
        <Fragment>
            <Table>
                <Head>
                    <Cell><Text>Issue Key</Text></Cell>
                    <Cell><Text>Summary</Text></Cell>
                    <Cell><Text>Status</Text></Cell>
                    <Cell><Text>Assignee</Text></Cell>
                    <Cell><Text>Priority</Text></Cell>
                    <Cell><Text>Created</Text></Cell>
                    <Cell><Text>Updated</Text></Cell>
                </Head>
                {issues.map(issue => (
                    <Row>
                        <Cell>
                            <Text>
                                <Link href={`https://nleyes.atlassian.net/browse/${issue.key}`}>{issue.key}</Link>
                            </Text>
                        </Cell>
                        <Cell>
                            <Text>
                                <Link href={`https://nleyes.atlassian.net/browse/${issue.key}`}>{issue.fields.summary}</Link>
                            </Text>
                        </Cell>
                        <Cell><Text>{issue.fields.status.name}</Text></Cell>
                        <Cell><Text>{issue.fields.assignee ? issue.fields.assignee.displayName : "Unassigned"}</Text></Cell>
                        <Cell><Text>{issue.fields.priority.name}</Text></Cell>
                        <Cell><Text>{new Date(issue.fields.created).toLocaleDateString()}</Text></Cell>
                        <Cell><Text>{new Date(issue.fields.updated).toLocaleDateString()}</Text></Cell>
                    </Row>
                ))}
            </Table>
            <Text>Total Issues: {issues.length}</Text>
            <Button text="Refresh" onClick={refreshIssues} />
        </Fragment>
    );
};

export const run = render(<Macro app={<JiraMacro/>}/>);

The code above successfully fetches Jira issues and displays them in a table format. However, when I tried to introduce a TextField to implement search functionality, I encountered the following challenges:

  1. When introducing the TextField outside a Form component, I received a validation error indicating that the TextField must be used within specific contexts (like Form, ConfigForm, MacroConfig, etc.)
  2. I tried wrapping the TextField inside a Form component, but then faced a generic error: “Cannot read property ‘prop’ of undefined.”

Given these challenges:

  • How can I successfully integrate the TextField or any other input method to introduce a search functionality in my macro?
  • Are there any known issues or workarounds for the errors I encountered?
  • If direct integration is problematic, are there any recommended alternative approaches to achieve this search functionality?

Any insights, suggestions, or code examples would be greatly appreciated.

I really appreciate any help you can provide.

By the way, I already asked before here: Seeking Guidance for Building a Custom Macro to Implement Search Functionality on a Confluence Page with JIRA Issue/Filter Macro how to achieve this and in how I found my way to start this.

UI Kit 2 seems to have a standalone TextField with onChange: https://developer.atlassian.com/platform/forge/ui-kit-2/text-field/

The geniuses who run Forge decided to add a 4th component library to the Atlassian ecosystem: AUI, Atlaskit, UI Kit, UI Kit 2. None are compatible with each other.

Before they rug-pull UI Kit 2 with UI Kit 3, you might be better off just building with Custom UI and dealing with the awful DX of invoking server-side functions.

Hi @nathanwaters ,

Thank you for pointing us towards UI Kit 2. We tried to install the latest version of @forge/ui expecting it to be version 2.x, but it seems that the 2.x version isn’t available on npm yet. Can you confirm if this has been your experience as well?

In light of this, we’re considering switching to Custom UI for greater flexibility. We’d appreciate any insights or advice you might have on this transition, especially any challenges or pitfalls we should be aware of.

Thanks again for your help!

Best regards,
@OdayRafeh

UI Kit is @forge/ui
UI Kit 2 is @forge/react

It makes no sense. Welcome to the Atlassian dev ecosystem lol. fyi @AdamMoore

For Custom UI, start with the tutorial: https://developer.atlassian.com/platform/forge/build-a-custom-ui-app-in-confluence/

It’s buggy. I can only ever get it to work in Firefox (not Chrome). The tutorial doesn’t say this for some reason, but the best way is to run two terminals: one running npm start in your static folder and forge tunnel in root folder. You also need to include a tunnel port (also not in the tutorial).

The tunnel will timeout supposedly every 2 hours without warning (it’ll appear to still be working but it’s disconnected). You won’t get any useful error messages. The apps run much slower than on Connect. Working out how to pass data back and forth via the invoke bridge is a painful and slow dev process. Permissions are excessively granular and poorly documented: eg if you use any custom CSS you need to include unsafe-inline in the permissions.

Good luck :slight_smile:

Thanks for you feedback on this @nathanwaters

I can see how the packages associated with UI Kit 1 (@forge/ui) and UI Kit 2 (@forge/react) can be confusing and we debated on the most appropriate name.

The main differences between UI Kit 1 and UI Kit 2 are that UI Kit 1 application code runs in remotely, whereas UI Kit 2 runs on the client (during the EAP phase it was known as “Client-side UI Kit” but we renamed it to be UI Kit 2 as it will ultimately be the successor to UI Kit 1).

The other major difference is that UI Kit 2 uses a real React development environment (whereas UI Kit 1 uses a “pseudo” React environment). This means that you can use any valid React code (like hooks) in your application although you are still restricted to ultimately render UI Kit components.

This is why the package was named @forge/react

I can only ever get it to work in Firefox (not Chrome)

It would be useful if you could share more about the problems you’ve experienced with Chrome to see if we can reproduce and resolve them.

1 Like

I think it’s a caching issue that’s been posted a few times in the forums. Just tried a test and it works now for me in Chrome.

Thanks for getting back to me… yes, there were a few issues in the EAP phase, but hopefully we ironed them out for Preview.

@nathanwaters Thanks for your Help man.