I am trying to build a table fetching data from a web api using TypeScript Azure DevOps UI Table
It's similar to this example here Sanbox instead if using the const mock data, I try to supply it with Web API data.
So I have successfully get the data from web api, however the table just can't get updated async data from web api
So how do you build a table that will dynamically updated data from web api? or every time it refresh page it can fetch latest data?
This is potentially a really big question, which is a little unfair to expect that anyone can provide a succinct simple answer. However, I can start you down the right path of discovery.
The short answer is you create an observable collection to hold the data and then use node's fetch(url)
to get the data and then push into your array.
export class TableExample extends React.Component {
// define an item provider to hold your data
private itemProvider = new ObservableArray<ITableItem>();
public async componentDidMount() {
await SDK.init();
await this.fetchData();
await SDK.ready();
}
private async fetchData() : Promise<void> {
const url = "<your-url>"
// fetch the data
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
let data = await response.json();
this.itemProvider.removeAll();
this.itemProvider.push(...toTableItem(data));
}
private function toTableItem(data: any[]) : ITableItem[] {
return data.map((item) => {
let r = {} as ITableItem;
// read the data from your json response into your table record
r.age = item.age;
return r;
});
}
public render(): JSX.Element {
return (
<Table
columns={ fixedColumns }
itemProvider={this.itemProvider}}
scrollable={true}
/>
);
}
}
This is based loosely on the table example you referenced from the design system.
The longer answer, which represents a much larger set of problems, is handling things like: where the URL comes from and the authentication methods, asynchronous loading, pagination, caching, etc. For example, never hard-code the URL and authentication scheme into your extension and check that into source -- instead you'll want to do some research on how extensions can store their own configuration data. This also implies that to store your own data you'll need an administration screen and ability to detect permissions, etc.
I will however give you this additional tip. You can show an empty table to represent a loading screen and then asynchronously show the data. To do this, you'll need to change the itemProvider to support both your data and empty data.
private itemProvider = new ObservableArray<
ITableItem | IReadonlyObservableValue<ITableItem | undefined>>();
constructor(props: {}) {
super(props);
// fill table with empty rows for a loading screen...
let emptyItems = new Array(5).fill(undefined);
this.itemProvider.push(
...emptyItems.map(() => ObservableValue<ITableItem | undefined>(undefined)));
}
public async componentDidMount() {
await SDK.init();
await SDK.ready(); // show the empty table
this.fetchData(); // asynchronously load the data
}