We just wrapped up AG Studio Launch Week See what we shipped

JavaScript Embedded AnalyticsLive Data

Version 3.1.0

Tables in the built-in engine can change in place. The application applies a transaction to add, update or remove rows, and every widget that reads the table shows the change, with no reload.

In the example above, Start Updates applies a transaction to the trades table every 100 milliseconds. The table and the chart show each change as it lands.

Accepting Transactions Copy Link

A table accepts transactions only when its data source allows them. Set transactions on a sync or columnar data source:

  • 'none', the default, accepts no transactions.
  • 'add' accepts added rows only.
  • 'all' also accepts updated and removed rows. It requires primaryKeyField, which names the field that identifies each row.
const studioProperties = {
    data: {
        sources: [{
            id: 'trades',
            transactions: 'all',
            primaryKeyField: 'id',
            data: [
                { id: 1, desk: 'Rates', quantity: 100 },
                // ... other rows
            ],
        }],
    },

    // other studio properties ...
}

Tables from an async data source accept no transactions. See Async Data Sources.

Applying a Transaction Copy Link

Get the engine with api.getDataEngine() once the studioReady event has fired, and call applyTransaction.

const engine = api.getDataEngine();
const position = await engine.applyTransaction({
    tableId: 'trades',
    remove: [2],
    update: [{ id: 1, desk: 'Rates', quantity: 120 }],
    add: [{ id: 3, desk: 'Credit', quantity: 10 }],
});
  • Rows are identified by the value of their primaryKeyField.
  • The parts apply in the order remove, update, add. To change a row's key, remove the row and add it again under the new key.
  • Each row in update replaces the whole row, so give every field the row keeps.
  • If any part is invalid, such as a key the table does not hold, the engine rejects the whole transaction and the table does not change.

The promise resolves once the change is committed, so a query made after that sees the new rows. It resolves with the table's new position: a number that goes up with each change to the table.

tableIdCopy Link
string
The table to change.
AgDataTransactionRows | AgDataTransactionColumns
Rows to add, as row objects or as columns. Accepted by a table whose transactions is 'add' or 'all'. On a table with a primaryKeyField, each row must carry a key no other row holds once remove has applied.
updateCopy Link
AgDataTransactionRows | AgDataTransactionColumns
Replacement rows, as row objects or as columns. Each is a whole row carrying the key of the row it replaces, and every field the row should keep. Requires a table whose transactions is 'all'.
removeCopy Link
unknown[]
Keys of the rows to remove. Requires a table whose transactions is 'all'.

Changing Several Tables Together Copy Link

Pass an array of transactions to change several tables as one change. Either every transaction applies or none does, and no query result reflects some of the tables changed and not others. The promise resolves with each changed table's new position, by table id.

const positions = await engine.applyTransaction([
    { tableId: 'trades', add: [{ id: 7, desk: 'FX', quantity: 5 }] },
    { tableId: 'desks', add: [{ desk: 'FX', region: 'AMER' }] },
]);
// positions.trades and positions.desks are the two tables' new positions

Frequent Changes Copy Link

Call applyTransaction for each change as it arrives. Transactions apply in the order they are called. Transactions called while an earlier one is still being applied are applied together, and resolve with the same position.

A widget does not run its queries once for each transaction. Changes that land while its queries run are shown together, by the next run.

What Widgets Show Copy Link

When a table changes, only the widgets with a query that reads it run their queries again. Filters and cross filters apply to the new data as they did to the old.

  • Tables and Pivot Tables update in place on the next frame after their queries have run. Selected rows and open row groups stay as they were. They can also animate changed values, using the Highlight Changes toggle on the Format tab.
  • Charts redraw on the next frame after their queries have run.
  • Other widgets refresh at most once a second, with the latest data. The states between two refreshes are not shown.

When two of a widget's queries read the same table, the widget never shows one query's data from before a change to that table beside the other's from after it. A widget in a hidden browser tab updates when the tab is shown again.

Each widget is kept up to date on its own, so while the data is changing two widgets can briefly show it at different points. Once the data stops changing, every widget shows the latest data within about a second.

A Custom Widget chooses how it is kept up to date.

Transactions, Data Updates and Reloads Copy Link

TransactionNew data propertyapi.reload()
ChangesRows of the tables named, in placeThe data of the sync data sources passedNothing in place: async data sources are fetched again
Cached resultsKept for the tables not changedClearedCleared
WidgetsThose that read a changed table run their queries againEvery widget loads its data againEvery widget loads its data again

See Reloading Sync Data and Reloading Async Data.

Async Data Sources Copy Link

A table from an async data source accepts no transactions. When its data changes, call api.reload() to show the change.

An async data source's getData must not run queries on the engine it supplies data to, directly or through Studio, and must not wait for anything that is itself waiting for a transaction. A transaction to a table waits for the queries reading it, and a query can be waiting for getData, so such a wait can hold up every update on the dashboard.