Dashboard Gadget Custom UI - Manipulate configuration object

Hey,

I am new to developing Forge Apps.
I am currently developing a dashboard gadget with the Custom UI.
The gadget should display an array of objects.

In the edit page I have an array data which contains several objects (created by input fields and selects). By submitting the form I set the gadget config via await view.submit(data).
The config is displayed correctly on the view page.

As soon as I go back to the edit page, the current config is loaded.
After I manipulate the current config and submitting it, for example by deleting the last object, the new config is not displayed correctly in the view page.

It looks like the old and the new config are merged. It is possible to edit a single objects in the config but deleting a specific object is not working.

Example:

  1. Edit Page Data: [{name: 'test'}, {name: 'random'}]
    View Page Config Output: {{name: 'test'}, {name: 'random'}}
    CORRECT

  2. Manipulate second object (rename random to foo):
    Edit Page Data: [{name: 'test'}, {name: 'foo'}]
    View Page Config Output: {{name: 'test'}, {name: 'foo'}}
    CORRECT

  3. Delete first object ({name: 'test'}):
    Edit Page Data: [{name: 'foo'}] =>
    View Page Config Output: {{name: 'foo'}, {name: 'foo'}}
    NOT CORRECT

Does await view.submit(data) not overwrite the latest/current config?

If the old and the new config are only merged, is there another way to delete/overwrite the current config?

Am I doing something wrong?

1 Like

Hey @AthanasiosGiannakopo,

Thanks for the detailed example, yes, view.submit(data) should overwrite the previous config, unless some fields are linked incorrectly. To ensure I replicate it correctly, are you deleting the object from the dashboard view, or through the config?

Cheers,
Yuwei

Hey @YuweiShen,

thanks for the reply.
I am manipulating (deleting objects) in the config (edit) view.

My code works like that:

Edit/Config view code

  1. Load current config from context:
const [data, setData] = useState([]);

useEffect(() => {
      view.getContext().then(({extension}) => {
          const gadgetConfiguration = extension.gadgetConfiguration;
          const gadgetConfigToArray = Object.values(gadgetConfiguration);
          setData(gadgetConfigToArray);
      });
}, []);
  1. Display Data
return (
      <Form onSubmit={onSubmit}>
          {({formProps}) => (
              <form {...formProps}>
                  ...
                  <FormSection>
                          {data.map((entry, index) => (
                              // display data here (input fields, select ...)
                          ))}
                  </FormSection>
                  ...
              </form>
          )}
      </Form>
);
  1. Delete specific object in data (through button click)
const handleRemove = (index) => {
    setData(data.filter((_, i) => i !== index));
};
...
<Button
      type="button"
      appearance="danger"
      onClick={() => handleRemove(index)}
>
      Remove
</Button>
...
  1. Submit Data
const onSubmit = async () => {
    await view.submit(data);
};

View Code

function View() {
  const [context, setContext] = useState();

  useEffect(() => {
    view.getContext().then(setContext);
  }, []);

  if (!context) {
    return 'Loading...';
  }

  return (
    <div>
      {JSON.stringify(context.extension.gadgetConfiguration)}
    </div>
  );
}

Hi, @AthanasiosGiannakopo ,

Thanks for providing us the detailed info and code snippet.

Based on the documentation: https://developer.atlassian.com/platform/forge/manifest-reference/modules/jira-dashboard-gadget/#extension-context

It is suggested that gadgetConfiguration expects object type instead of array type, hence sending through an array through view.submit is not formally support.

Additionally the current behaviour in updating the gadgetConfiguration object is indeed based on patching instead of full overwrite. Hence, in order to unset / remove an key-value pair from the gadgetConfiguration object, it is suggested to set the value to null or undefined.

In order to achieve what you are trying to do (i.e. represent fields as an array), it is possible to nest the array in the gadgetConfiguration for that purpose. For example:

      view.submit({
        fields: [
          {
            name: "name",
            value: "New name",
          },
          {
            name: "description",
            value: "New description",
          },
        ],
      });

That is, instead making gadgetConfiguration an array, the array could be set under gadgetConfiguration.fields. This way, you will have full control on how array could be manipulated.

Hope this information is useful to you!

Thanks!

Soloman

3 Likes

Hey @SolomanWeng,

thanks for your help.

This has solved my problem. Everything is now working as expected.

Thanks!
Atha

1 Like