Configuration allows you to customize what the macro displays by adjusting settings in a form. To access these settings, you need to go into the edit mode for the macro, as demonstrated below. This gives you the ability to customize the macro's output according to your preferences.
Make sure you have the following:
npm install -g @forge/cli@latest
on the command line.npm install @forge/react@latest --save
on the command line. If your macro uses Custom UI, navigate to the resource directory and run the same command.In this tutorial, we will add fun facts about pets which are passed through configuration we create.
We recommend you to change the values as listed in the below manifest.yml
file.
Make sure you run forge login
before you creating your app. For more information on how to log in
to Forge, see Log in with an Atlassian API token.
Create an app using a template.
Navigate to the directory where you want to create the app.
Create your app by running:
1 2forge create
Enter a name for the app.
Select the UI Kit category from the list.
Select the confluence-macro template from the list.
Change to the app subdirectory to see the app files
To add configuration to the Confluence macro module:
manifest.yml
file.config
property with the value set to true
.After doing this, your manifest.yml
should look like the following, with your own values
for each of the properties.
1 2modules: macro: - key: pet-facts resource: main render: native resolver: function: resolver title: Pet config: true function: - key: resolver handler: index.handler resources: - key: main path: src/frontend/index.jsx app: id: "<your app id>"
You can create a new function component that will return the configuration (Config) components. The config components must be selected from the following list:
Configuration is stored in key-value pairs corresponding to each form component.
We recommend clearing the src/frontend/index.jsx
file and replacing it with the provided code
for error-free results.
src/frontend/index.jsx
file, create a function component that constructs
the configuration of the UI Kit components you're using:1 2import React from 'react'; import { Label, Textfield } from '@forge/react'; const Config = () => { return ( <> <Label>Pet age</Label> <Textfield name="age" /> </> ); };
The use of Label
in the macro configuration is different from that of other extension points. It does not use the labelFor
and id
properties and will instead be rendered in the order specified in the app. See the Label in the macro configuration documentation for more details.
src/frontend/index.jsx
file, call the addConfig
method on ForgeReconciler
with your config element. Ensure you have ForgeReconciler
imported at the top.1 2import React from 'react'; import ForgeReconciler, { Label, Textfield } from '@forge/react'; const Config = () => { return ( <> <Label>Pet age</Label> <Textfield name="age" /> </> ); }; const App = () => { ... } ForgeReconciler.render( <React.StrictMode> <App /> </React.StrictMode> ); ForgeReconciler.addConfig(<Config />);
Note: Changing the name
property of a field is treated as removing the field and adding a new one.
You access the config for a macro in your app code with the
getContext method. When this method resolves,
it returns the product context, which will include the key-value pairs set in the config.
The key is the name
property on the form component in configuration, and the value is what the user enters.
In your src/frontend/index.jsx
file:
useState
and useEffect
.1 2import React, { useState, useEffect } from 'react'; // useState: Adds and updates local state to a component. // useEffect: Executes a specific function whenever any value in its dependency array (the second argument of the hook) changes.
view
from @forge/bridge
in your app code.1 2import { view } from '@forge/bridge';
Label
, Text
, Textfield
components.1 2import ForgeReconciler, { Label, Text, Textfield } from '@forge/react';
App
and call the getContext
method in the useEffect
to get the product context.1 2const Config = () => { ... }; const App = () => { const [context, setContext] = useState(undefined); useEffect(() => { view.getContext().then(setContext); }, []); return ( <> <Text>Hello World</Text> </> ); };
age
to the return statement.1 2const App = () => { ... const config = context?.extension.config; const age = config?.age; return ( <> <Text>Hello World</Text> <Text> {age || 'Fetching config...'} </Text> </> ); }
The index.jsx
file should look like this:
1 2import React, { useState, useEffect } from 'react'; import ForgeReconciler, { Label, Text, Textfield } from '@forge/react'; import { view } from '@forge/bridge'; const Config = () => { return ( <> <Label>Pet age</Label> <Textfield name="age" /> </> ); }; const App = () => { const [context, setContext] = useState(undefined); useEffect(() => { view.getContext().then(setContext); }, []); const config = context?.extension.config; const age = config?.age; return ( <> <Text>Hello World</Text> <Text> {age || 'Fetching config...'} </Text> </> ); }; ForgeReconciler.render( <React.StrictMode> <App /> </React.StrictMode> ); ForgeReconciler.addConfig(<Config />)
We recommend you add sensible defaults for each of your configuration values.
If it's more sensible for the macro to not have default configuration values, we recommend you display a section message with the appropriate instructions, as shown below:
1 2import ForgeReconciler, { Label, Text, Textfield, SectionMessage } from '@forge/react'; //Add SectionMessage to the import statement <SectionMessage title="You need to configure this macro" appearance="warning"> <Text> While editing the page, select the macro, and click on the pencil icon to display configuration options. </Text> </SectionMessage>
You can also add a state to only display the section message if the macro has not already been configured; otherwise, it will always show on the macro.
You can create a new function component that will return the configuration (Config) components. The config components must be selected from the following list:
Configuration is stored in key-value pairs corresponding to each form component.
Make sure you run forge login
before you creating your app. For more information on how to log in
to Forge, see Log in with an Atlassian API token.
Create an app using a template.
Navigate to the directory where you want to create the app.
Create your app by running:
1 2forge create
Enter a name for the app.
Select the Custom UI category from the list.
Select the confluence-macro template from the list.
Change to the app subdirectory to see the app files
This assumes you are using a Custom UI template with the resource in static/hello-world
. If you are not using a template, adjust the paths as needed.
static/hello-world/src/Config.js
file, create a function component that constructs
the configuration of the UI Kit components you're using:1 2import React from 'react'; import { Label, Textfield } from '@forge/react'; const Config = () => { return ( <Label>Pet Age</Label> <Textfield name="age" /> ); }; export default Config;
static/hello-world/src/index.js
file, call the addConfig
method on ForgeReconciler
with your config element. Ensure you have ForgeReconciler
imported at the top.1 2import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import Config from './Config'; import ForgeReconciler from "@forge/react"; ReactDOM.render( <App />, document.getElementById('root') ); ForgeReconciler.addConfig(<Config />);
To retrieve the configuration, follow the same steps as above but in your static/hello-world/src/App.js
file instead. You can then use the configuration values in your app.
1 2import React, { useState, useEffect } from 'react'; import { view } from "@forge/bridge"; const App = () => { const [context, setContext] = useState(undefined); useEffect(() => { view.getContext().then(setContext); }, []); const config = context?.extension.config; const age = config?.age; return ( <> <div>Hello World</div> <div> {age || 'Fetching config...'} </div> </> ); } export default App;
In this example, by default, the macro displays Unnamed Pet is 0 years old.
Create a default configuration for the pet's name and age, and then
add defaultConfig
variable to const config = context?.extension.config
In your src/frontend/index.jsx
file outside the Config
and App
components, add:
1 2const defaultConfig = { name: 'Unnamed Pet', age: '0' };
Then replace the const config
inside the App
component with the following:
1 2const config = context?.extension.config || defaultConfig;
Now that we have created configurations (name
and age
) for your macro, we can now enhance
this feature to include dynamic input for the pet's name and age.
For example, if a user submits the name Fluffy and age 2, the macro displays Fluffy is 2 years old.
In your index.jsx
file:
1 2const Config = () => { return ( <> <Label>Pet name</Label> <Textfield name="name" defaultValue={defaultConfig.name} /> <Label>Pet age</Label> <Textfield name="age" defaultValue={defaultConfig.age} /> </> ); };
In the return
statement of the App
component:
Replace
1 2<Text>Hello World</Text> <Text> {age || 'Fetching config...'} </Text>
with
1 2return ( <Text>{config.name} is {config.age} years old.</Text> );
Your main file containing the application's root component (here index.jsx
) should look like this:
1 2import React, { useEffect, useState } from 'react'; import ForgeReconciler, { Label, Textfield, Text, SectionMessage } from '@forge/react'; import { view } from '@forge/bridge' const defaultConfig = { name: 'Unnamed Pet', age: '0' }; // Function that defines the configuration UI for the pet's name and age const Config = () => { return ( <> <Label>Pet name</Label> <Textfield name="name" defaultValue={defaultConfig.name} /> <Label>Pet age</Label> <Textfield name="age" defaultValue={defaultConfig.age} /> </> ); }; const App = () => { const [context, setContext] = useState(undefined); // Retrieve the context useEffect(() => { view.getContext().then(setContext); }, []); const config = context?.extension.config || defaultConfig; // Displaying the pet's name and age using the configuration values. SectionMessage component is optional. return ( <> <Text>{config.name} is {config.age} years old.</Text> <SectionMessage title="You need to configure this macro" appearance="warning"> <Text> While editing the page, select the macro, and click on the pencil icon to display configuration options. </Text> </SectionMessage> </> ); }; // Adding the Config function to the ForgeReconciler to allow for configuration changes ForgeReconciler.render( <React.StrictMode> <App /> </React.StrictMode> ); ForgeReconciler.addConfig(<Config />);
If you haven't done so already, make sure you have installed the latest version of UI Kit
before you begin deploying your app. Navigate to the top-level directory of the app
and run npm install @forge/react@latest --save
on the command line.
Build, deploy, and install the app to see it in your Confluence site.
To use your app, it must be installed onto an Atlassian site. The
forge deploy
command builds, compiles, and deploys your code; it'll also report any compilation errors.
The forge install
command then installs the deployed app onto an Atlassian site with the
required API access.
You must run the forge deploy
command before forge install
because an installation
links your deployed app to an Atlassian site.
Navigate to the app's top-level directory and deploy your app by running:
1 2forge deploy
Install your app by running:
1 2forge install
Select your Atlassian product using the arrow keys and press the enter key.
Enter the URL for your development site. For example, example.atlassian.net. View a list of your active sites at Atlassian administration.
Once the successful installation message appears, your app is installed and ready
to use on the specified site.
You can always delete your app from the site by running the forge uninstall
command.
Running the forge install
command only installs your app onto the selected product.
To install onto multiple products, repeat these steps again, selecting another product each time.
Note that the Atlassian Marketplace
does not support cross-product apps yet.
You must run forge deploy
before running forge install
in any of the Forge environments.
Pet age
, Pet name
, and then close the configuration page. The config values are saved automatically.You should now see the config values displayed within the app.
Rate this page: