Skip to Content

Events API

Event System Overview

The GoCharting SDK reports events through three channels:

ChannelHow you listenTypical use
Config callbacksonReady, onError, appCallback in createChart() / <GoCharting />Lifecycle + trading / UI actions
Widget buschart.subscribe(event, cb) / chart.unsubscribe(event, cb)Layout, active chart, autosave, screenshots
Chart instancechart.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). Call onClose() after handling the event to dismiss that popup. It is undefined for 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; } };
Note

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 eventFrom appCallbackPayloadWhen it fires
layoutCHART_MODE_CHANGEDMultiChartInfoMultichart grid changes (setLayout, layout chooser, etc.)
activeChartChangedCHART_SELECTEDChart selected msgActive pane changes (setActiveChart, click, sync)
onAutoSaveNeededundefinedDebounced 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
onScreenshotReadyimage URL stringAfter takeScreenshot() resolves with a saved URL
drawing_eventDrawingEventParamsDrawing created or removed (type, objectId, chartId)
Tip

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 URL

Chart-level subscriptions (activeChart())

Per-pane observers return an ISubscription (subscribe(cb) → unregister). Documented in detail on the Chart API (Phase 1E — activeChart() events):

MethodPayloadFires when
onSymbolChanged()voidSecurity / symbol changes
onIntervalChanged()voidInterval changes
onChartTypeChanged()voidChart type changes
onDataLoaded()voidLoading finishes
onVisibleRangeChanged(){ from, to } (unix sec)Visible time range changes
crossHairMoved(){ time, price }Crosshair moves
onHoveredSourceChanged()entity info or nullHovered study/drawing changes
onDrawingEvent()DrawingEventParamsDrawing 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 TypeMessage PayloadDescription
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_POSITIONSPosition dataUser requested to close all positions
CANCEL_ALL_ORDERSOrder dataUser 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 TypeMessage PayloadDescription
CREATE_ALERT{ alert: { symbol, price, condition, message? } }User created an alert (context menu or bottom bar)
MODIFY_ALERTAlert dataUser modified an existing alert

Chart Events

Event TypeMessage PayloadDescription
CHART_SELECTED{ id, chartId, idx, symbol, interval }Active chart changed — also subscribe("activeChartChanged")
CHART_MODE_CHANGEDMultiChartInfo (see above)Layout changed — also subscribe("layout")
Note

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 TypeMessage PayloadDescription
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
Note

SAVE_CONFIGURATION_STORE is handled internally by the SDK when chart configuration changes and is not forwarded to your appCallback.

Data Events

Event TypeMessage PayloadDescription
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
Note

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?.()); }, });

For more event handling examples, see the tutorials section.

Last updated on