Reference
Events
What the chart tells you, and the exact shape of each message. Subscribe once; every event arrives on the same handler.
Subscribing
const chart = vpEmbed.chart(document.querySelector('.vp-chart'));
const off = chart.on('orderMove', ({ handle, price }) => {
// The reader dragged a line. Nothing has happened to your order yet.
void updateMyOrder(handle, price);
});
off(); // on unmount. There is no off(name, fn).on RETURNS the unsubscriber rather than offering an off(name, fn), because that form needs the caller to hand back the same function reference and the failure when they do not is a handler firing twice, which nobody notices until it does something twice. In a component, call it from the teardown. Nothing else unsubscribes: a chart that is removed from the page takes its listeners with it, but a chart that is kept and re-subscribed to does not.event message with { name, payload }, see Wire messages.State changes
Fired whether the change came from you or from the reader, so a handler cannot tell them apart, and should not need to. Nothing here expects a reply.
| Event | Payload | When it fires |
|---|---|---|
symbolChanged | { symbol } | You or the reader changed instrument. |
intervalChanged | { interval } | The resolution changed, from either side. |
chartTypeChanged | { type } | The chart type changed. |
dataLoaded | {} | A page of bars has been drawn. A good moment to place your lines. |
visibleRangeChanged | { from, to } | The reader panned or zoomed. Seconds. |
priceScaleChanged | { from, to, top, height, left, width, scale, inverted } | The price-to-pixel mapping moved: a new range, a resized iframe, or the reader switching to a log or inverted scale. Subscribe to keep your own overlay pinned to the chart. Fires once as soon as the chart has laid out, so a page can draw at mount rather than waiting for the reader to move something, and at most once per animation frame. |
dataLoaded is the moment worth waiting for before placing lines. Bars are drawn, so a price you place has somewhere to sit; before it, the chart has a symbol and an empty plot.Trading interactions
These are the whole reason the chart can carry orders. Every one is a request from the reader, not a thing that has happened: the frame has no venue, no account and no idea whether you accepted it.
| Event | Payload | When it fires |
|---|---|---|
orderSubmit | { side, type, price, quantity, symbol } | The reader picked Buy or Sell at a level. A request rather than a fill: the frame has no venue and no account, so your page decides. type is limit or stop, derived from which side of the market the level is on. Only ever fires after setTrading. |
orderMove | { handle, price } | An editable order line was dragged. Fires on RELEASE, never during the drag. |
orderModify | { handle, price } | An order line’s body was CLICKED rather than dragged, a press that never travelled. Distinct from orderMove on purpose: one says the reader put the level somewhere new, this says they want whatever ticket you keep for it. |
orderCancel | { handle } | The cancel button on a cancellable order line was pressed. |
positionClose | { handle } | A closeable position line was closed. |
positionModify | { handle, price } | A position line’s body was clicked. Open whatever ticket you keep for that position. |
positionReverse | { handle } | The reverse control was pressed. Only ever fires on a line you made reversible. |
positionMove | { handle, price } | An editable position line was dragged, on RELEASE. Absent on an ordinary position line, which does not drag at all. |
positionAddTakeProfit | { handle, price } | The reader pulled the TP handle off the pill and let go. price is where they RELEASED, not the position’s entry. A request, exactly like orderSubmit: nothing is drawn as a result, and the way you answer is to set takeProfit on the line and turn canAddTakeProfit off, which keeps what is on the chart equal to what your venue actually holds. |
positionAddStopLoss | { handle, price } | The same gesture on the stop handle. Answer it by setting stopLoss and clearing canAddStopLoss. |
handle.set() to confirm or to put it back. A chart that snapped the line to a price the exchange rejected would be showing a resting order that does not exist.orderMove fires on RELEASE, never during the drag. A per-pixel stream would be a request per frame at your endpoint, and the reader has not decided anything until they let go.positionReverse needs reversible, positionMove needs editable, and the two bracket handles need canAddTakeProfit / canAddStopLoss. A line drawn with none of them reports only positionClose and positionModify, which is what an embed drew before those properties existed. See Objects.Your own control
One event, and it is the whole of what a toolbar button does: the frame draws your label in the chart's own header and tells you when it was pressed. Every consequence is yours. See createToolbarButton on Methods you call.
| Event | Payload | When it fires |
|---|---|---|
toolbarButtonClick | { handle } | A toolbar button you added was pressed, by pointer or by keyboard. The whole of what such a button does: the frame draws a label and reports the press, and every consequence is yours. |
The reader's preferences
The embed writes no storage, so a timeframe the reader stars is gone on the next page load unless you keep it. The list also rides saveState under favoriteIntervals, and loadState puts it back, so a page that already saves the chart needs nothing more than to save on this event too.
| Event | Payload | When it fires |
|---|---|---|
favoriteIntervalsChanged | { intervals } | The reader starred or unstarred a timeframe in the interval menu. intervals is the whole list, in menu order. The embed keeps nothing between page loads, so this is your cue to save it, by itself or through saveState. Restoring a list with loadState does not fire it. |
The handle field
Four of the trading events carry handle, the same value the create* call resolved to. It is how you know WHICH of your lines the reader touched, so keep it beside whatever it represents in your own state.
const orders = new Map();
const line = await chart.createOrderLine({ price: 42000, text: 'Bid', editable: true });
orders.set(line.handle, myOrderId);
chart.on('orderMove', ({ handle, price }) => {
const id = orders.get(handle); // ← which order this was
void amendOrder(id, price);
});{ id, price } from memory where the wire sends { handle, price }, it destructures to undefined and looks completely reasonable while doing so. Every payload above is now compared against the emitter key by key on every build.