Examples of Dynamic Table cannot be run successfully

Hi,
I can’t run the sample codes as expected. A blank page will be rendered if I add the rows to the codes. If I remove rows (keep head there), the page is ok)

https://developer.atlassian.com/platform/forge/ui-kit/components/dynamic-table/

// applied as rows in the form
export const rows = presidents.map((president, index) => ({
  key: `row-${index}-${president.name}`,
  cells: [
    {
      key: createKey(president.name),
      content: <Link href="">{president.name}</Link>,
    },
    {
      key: createKey(president.party),
      content: president.party,
    },
    {
      key: president.id,
      content: president.term,
    },
  ],
}));

Anyone could help? thanks,
YY

Hi @YY1 ,
I could make the example work this afternoon. Hard work. But, good news, it’s possible :wink: .
Did you try to display the console of the Chrome developer tools? You will have additional information on what is going wrong.
And don’t forget to paste all the code, and make sure to paste the ‘export const presidents’ block first (otherwise the rows part don’t find the presidents variable).
Good luck :slight_smile:

1 Like

Thanks @BertrandDrouhard1
I’m getting it running now. But I found some blank and 0 values are changed:

Hi @YY1 , could you share a small code snippet on that first row where the table is rendering values that you’re not expecting?

Hi @QuocLieu
I noticed that when initializing the app/page, the presidents may be empty. So I added presidents && and it worked correctly.

const rows = presidents && presidents.map((president, index) => ({
  key: `row-${index}-${president.name}`,

Thanks for your help.

1 Like

@YY1

I’m stuck in basics, please can you help me to understand which files should have a the code from example. I did the following, there are no errors but pages doesn’t load with anything. Please can you help me what is going wrong? I suspect it is where i have copied the code could be an issue. Thanks for help in advance.

  1. /frontend/data
    created “data” file with all row, heard and president exports.

  2. /frontend/index.jsx have
    import { DynamicTable } from “@forge/react”;
    import { head, rows } from “./data”;
    export default function TableEmpty() {
    return (

    );
    };

  3. /resolver/index.jsx have below code.
    const createKey = (input) => {
    return input ? input.replace(/^(the|a|an)/, “”).replace(/\s/g, “”) : input;
    }

  4. src/index.jsx have
    export { handler } from ‘./resolvers’;
    export { rows } from ‘./resolvers’;
    export { head } from ‘./resolvers’;

Hi! I recommend looking at one of the example apps with a similar layout of src/frontend and src/resolvers. In this case, you’ll need:

  • A src/frontend/index.jsx file
  • A src/frontend/data.jsx file, with contents like:
import React from 'react';
import { Link } from '@forge/react';

export const createKey...
export const presidents...
export const rows...
export const head...

where those export lines are the data objects on the example.

  • As a general rule of thumb, if you have a import React from 'react'; in your file, the extension should be jsx. Otherwise, it should be .js.

  • Your manifest doesn’t need any resolvers, as you’re working with static data in the frontend. So you don’t need src/index.js or src/resolvers/index.js either.Think of the “resolvers” files as the files where all the actual interactions with the API are kept.

I also recommend getting familiar with Typescript and doing your Forge development in that. It’s a pain to get used to, but once you know it, you will encounter fewer bugs. Here’s my tsconfig.json file.

{
  "compilerOptions": {
    "module": "NodeNext",
    "target": "es2017",
    "sourceMap": true,
    "moduleResolution": "NodeNext",
    "esModuleInterop": true,
    "lib": ["dom", "dom.iterable", "es2017"],
    "types": ["node", "react"],
    "baseUrl": "./",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "allowJs": true,
    "jsx": "react",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "noPropertyAccessFromIndexSignature": true,
    "noUncheckedIndexedAccess": true,
  },
  "include": ["./src/**/*"]
}

Here’s my dependencies from devDependencies.json:

  "devDependencies": {
    "@types/node": "^20.12.5",
    "@types/react": "^18.2.74",
    "@typescript-eslint/parser": "^7.5.0",
    "eslint": "^8.57.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "openapi-typescript": "^6.7.5",
    "typescript": "^5.4.4"
  },
  "dependencies": {
    "@forge/api": "^3.2.0",
    "@forge/bridge": "^3.3.0",
    "@forge/react": "^10.1.0",
    "@forge/resolver": "^1.5.29",
    "react": "^18.2.0"
  }

While in development, execute npm update --save and npm update --save-dev frequently to update your dependencies to the latest versions as Atlassian is rolling out significant changes to the Forge node modules every week.

I recommend generating type files for the Atlassian APIs with OpenApi too, as that will also make your development much faster and less bug-ridden.

Atlassian hasn’t formally exported types for subcomponents for UIKit2 yet - for example, the RankEnd type in DynamicTable - but you can find them in @atlaskit/forge-react-types.

Thank you for the response @AlexvanVucht. Finally it worked. I used Hello World app code.

Created all data stuff in data.jsx and imported the data.jsx in frontend index.jsx.

Also added export rows and heads in src/index.js.

I don’t know if the approach is correct but it worked :slight_smile:

BTW, i didn’t understand the typeScript and devDependencies suggestion, it may be that i’m still new to this world. Thanks