Events API
Event System Overview
The GoCharting SDK reports events through three channels:
| Channel | How you listen | Typical use |
|---|---|---|
| Config callbacks | onReady, onError, appCallback in createChart() / <GoCharting /> | Lifecycle + trading / UI actions |
| Widget bus | chart.subscribe(event, cb) / chart.unsubscribe(event, cb) | Layout, active chart, autosave, screenshots |
| Chart instance | chart.activeChart().onSymbolChanged().subscribe(…) etc. | Per-pane symbol, interval, range, crosshair |
import { createChart } from "@gocharting/chart-sdk";
const chart = createChart("#chart-container", {
symbol: "BYBIT:FUTURE:BTCUSDT",
interval: "1m",
datafeed: myDatafeed,
licenseKey: "demo-550e8400-e29b-41d4-a716-446655440000",
onReady: (chartInstance) => {
console.log("Chart is ready!", chartInstance);
},
onError: (error) => {
console.error("Chart error:", error);
},
appCallback: (event) => {
console.log(event.eventType, event.message);
},
});
// Widget bus (after onReady / when the instance is returned)
chart.subscribe("layout", (info) => {
console.log("Layout changed:", info.layout, info.charts?.length);
});
chart.subscribe("activeChartChanged", (msg) => {
console.log("Active chart:", msg.idx, msg.chartId);
});The AppCallbackEvent Object
appCallback receives a single event object (not separate arguments):
interface AppCallbackEvent {
eventType: string; // Event name, e.g. "PLACE_ORDER"
message: any; // Event payload (shape depends on eventType)
onClose: ((...args: any[]) => void) | undefined; // Closes the SDK popup/UI that raised the event (when applicable)
}eventType— the event name (see the tables below).message— the event payload; its shape depends on the event type.onClose— some events are raised from an SDK popup (e.g. the order form). CallonClose()after handling the event to dismiss that popup. It isundefinedfor events that have no UI to close.
appCallback: (event) => {
switch (event.eventType) {
case "PLACE_ORDER":
submitToBroker(event.message.order);
if (event.onClose) event.onClose(); // dismiss the order form
break;
case "CREATE_ALERT":
console.log("Alert at price:", event.message.alert.price);
break;
case "CHART_MODE_CHANGED":
console.log("Layout:", event.message.layout);
break;
case "CHART_SELECTED":
console.log("Active chart:", event.message.chartId);
break;
}
};TypeScript: With the shipped type definitions, event.message is automatically narrowed based on event.eventType inside switch statements (see Type Definitions).
Widget subscribe / unsubscribe
Prefer the widget bus when you want TV-style listeners on the chart instance (no config required). Mapped names are aliases of appCallback chart events; raw eventType strings are also accepted.
function onLayout(info) {
console.log(info.layout, info.isMultichartingEnabled, info.charts);
}
chart.subscribe("layout", onLayout);
chart.unsubscribe("layout", onLayout);
// Equivalent raw name:
chart.subscribe("CHART_MODE_CHANGED", onLayout);| Subscribe event | From appCallback | Payload | When it fires |
|---|---|---|---|
layout | CHART_MODE_CHANGED | MultiChartInfo | Multichart grid changes (setLayout, layout chooser, etc.) |
activeChartChanged | CHART_SELECTED | Chart selected msg | Active pane changes (setActiveChart, click, sync) |
onAutoSaveNeeded | — | undefined | Debounced dirty signal (drawings/indicators); call host save |
onChartLoaded | — | { blob } | After a successful load() / restore |
chart_load_requested | — | { blob } | Host asked to load; before apply completes |
onScreenshotReady | — | image URL string | After takeScreenshot() resolves with a saved URL |
drawing_event | — | DrawingEventParams | Drawing created or removed (type, objectId, chartId) |
Layout changes always notify. setLayout("2") (and UI layout switches) emit CHART_MODE_CHANGED to appCallback and layout on chart.subscribe. Labs: phase2-layout-lab.html (CodePen ), phase0-1a-api-lab.html, phase5-persistence-lab.html (CodePen ).
MultiChartInfo (layout / CHART_MODE_CHANGED)
{
isMultichartingEnabled: true,
layout: "1|1", // GoCharting layout id
charts: [
{ id, chartId, idx: 0, symbol: "BTCUSDT", interval: "1m" },
{ id, chartId, idx: 1, symbol: "ETHUSDT", interval: "5m" },
],
}Persistence (Phase 5)
When autosave is enabled (see Configuration / chart save APIs), the widget bus emits:
chart.subscribe("onAutoSaveNeeded", () => {
chart.saveChartToServer?.(); // or your own persist path
});
chart.subscribe("onChartLoaded", ({ blob }) => {
console.log("Restored layout", blob?.layout);
});Debounce is controlled by autosave delay on the chart config (seconds).
Screenshots
chart.subscribe("onScreenshotReady", (imageUrl) => console.log(imageUrl));
await chart.takeScreenshot(); // also resolves with the URLChart-level subscriptions (activeChart())
Per-pane observers return an ISubscription (subscribe(cb) → unregister). Documented in detail on the Chart API (Phase 1E — activeChart() events):
| Method | Payload | Fires when |
|---|---|---|
onSymbolChanged() | void | Security / symbol changes |
onIntervalChanged() | void | Interval changes |
onChartTypeChanged() | void | Chart type changes |
onDataLoaded() | void | Loading finishes |
onVisibleRangeChanged() | { from, to } (unix sec) | Visible time range changes |
crossHairMoved() | { time, price } | Crosshair moves |
onHoveredSourceChanged() | entity info or null | Hovered study/drawing changes |
onDrawingEvent() | DrawingEventParams | Drawing created or removed |
const api = chart.activeChart();
const unsub = api.onSymbolChanged().subscribe(() => {
console.log("Symbol:", api.symbol());
});
api.onDrawingEvent().subscribe(({ type, objectId }) => {
console.log(type, objectId);
});
// later: unsub();Lab: phase1e-api-lab.html.
appCallback Event Types
Trading Events
Emitted when trading is enabled (trading.enableTrading: true) and the user interacts with trading UI (order forms, order/position lines, context menus).
| Event Type | Message Payload | Description |
|---|---|---|
PLACE_ORDER | { order, security, ltp } | User submitted an order (order form, one-click trade, context menu) |
MODIFY_ORDER | { orderId, order, security } | User modified an existing order (e.g. dragged the order line/TP/SL) |
EDIT_ORDER | { order } | User opened/edited an order via the order editing UI |
CANCEL_ORDER | { order } | User requested cancellation of an order |
MODIFY_POSITION | { position } (includes update/updateType fields) | User modified a position (e.g. dragged position TP/SL) |
CLOSE_POSITION | { position, chartIdx } | User clicked the position X (close) button |
EXIT_ALL_POSITIONS | Position data | User requested to close all positions |
CANCEL_ALL_ORDERS | Order data | User requested to cancel all orders |
PLACE_ORDER message example:
{
order: {
side: "buy", // "buy" | "sell"
orderType: "market", // "market" | "limit" | "stop" | "stopLimit"
price: 50000, // 0/undefined for market orders
size: 0.1,
task: "placement",
stopLoss: 49000, // optional
takeProfit: 52000, // optional
},
security: { symbol: "BTCUSDT", exchange: "BYBIT", segment: "FUTURE", /* ... */ },
ltp: 50100, // last traded price
}Alert Events
| Event Type | Message Payload | Description |
|---|---|---|
CREATE_ALERT | { alert: { symbol, price, condition, message? } } | User created an alert (context menu or bottom bar) |
MODIFY_ALERT | Alert data | User modified an existing alert |
Chart Events
| Event Type | Message Payload | Description |
|---|---|---|
CHART_SELECTED | { id, chartId, idx, symbol, interval } | Active chart changed — also subscribe("activeChartChanged") |
CHART_MODE_CHANGED | MultiChartInfo (see above) | Layout changed — also subscribe("layout") |
ON_LOAD is handled internally by the SDK when the chart UI finishes loading and is not delivered to your appCallback. Use the onReady callback instead to know when the chart is ready.
Save / Template Events
Emitted when the user saves charts or manages indicator templates from the chart UI. Use these to persist templates/layouts in your own backend. (Widget autosave uses onAutoSaveNeeded / onChartLoaded on chart.subscribe instead.)
| Event Type | Message Payload | Description |
|---|---|---|
SAVE_TEMPLATE | { key, name, data_type: "study", action: "INSERT", value, template } | User saved an indicator template |
DELETE_TEMPLATE | { key, data_type: "study", action: "DELETE", template } | User deleted an indicator template |
SAVE_CHART | { data_type: "chart", action: "INSERT", key, name, value } | User saved the chart layout |
SAVE_CONFIGURATION_STORE is handled internally by the SDK when chart configuration changes and is not forwarded to your appCallback.
Data Events
| Event Type | Message Payload | Description |
|---|---|---|
DOWNLOAD_MORE_DATA_BY_DATE | { params, store } | User jumped to a date (params is [start_date, end_date]); the SDK also requests the data itself |
Some events (e.g. DOWNLOAD_MORE_DATA, OPEN_TRADING_WIDGET, DELETE_ALERT, PLACE_ORDER_DIRECT, MODIFY_ORDER_DIRECT) are handled internally by the SDK and are not reliably forwarded to your appCallback. Unrecognized event types are forwarded as-is, so always include a default branch that ignores events you do not handle.
Complete Example
import { createChart } from "@gocharting/chart-sdk";
const chart = createChart("#chart-container", {
symbol: "BYBIT:FUTURE:BTCUSDT",
interval: "1m",
datafeed: myDatafeed,
licenseKey: "demo-550e8400-e29b-41d4-a716-446655440000",
trading: {
enableTrading: true,
showOpenOrders: true,
showPositions: true,
},
appCallback: (event) => {
switch (event.eventType) {
case "PLACE_ORDER":
console.log("Order:", event.message.order);
if (event.onClose) event.onClose();
break;
case "MODIFY_ORDER":
console.log("Modify order:", event.message.orderId);
break;
case "CANCEL_ORDER":
console.log("Cancel order:", event.message.order);
break;
case "MODIFY_POSITION":
console.log("Modify position:", event.message.position);
break;
case "CLOSE_POSITION":
console.log("Close position:", event.message.position);
break;
case "CREATE_ALERT":
console.log("Alert:", event.message.alert.price);
break;
case "SAVE_TEMPLATE":
saveToBackend(event.message.template);
break;
case "CHART_MODE_CHANGED":
console.log("Layout:", event.message.layout);
break;
case "CHART_SELECTED":
console.log("Chart selected:", event.message.chartId);
break;
default:
break;
}
},
onReady: (c) => {
c.subscribe("layout", (info) => console.log("layout", info.layout));
c.subscribe("onAutoSaveNeeded", () => c.saveChartToServer?.());
},
});Related Documentation
- Chart API - Chart creation,
setLayout,subscribe, chart-level subscriptions - GoCharting React Component - Declarative React API
- Configuration API - Chart configuration / autosave
- Trading API - Trading integration details
- Type Definitions - Typed event messages
- Trading Integration - Trading features
- Examples - Working implementations
For more event handling examples, see the tutorials section.