
Security News
ECMAScript 2025 Finalized with Iterator Helpers, Set Methods, RegExp.escape, and More
ECMAScript 2025 introduces Iterator Helpers, Set methods, JSON modules, and more in its latest spec update approved by Ecma in June 2025.
ngx-lightweight-charts
Advanced tools
An easily extendable Angular wrapper for Trading View lightweight-charts
A wrapper that exposes core chart functionality within an Angular app, and allows new functionality to be easily added.
A (re)implementation of the entire lightweight-charts
api.
Version | Angular version |
---|---|
0.3.x | 18 |
0.2.x | 17 |
Installation
npm i ngx-lightweight-charts
Add providers
import { ApplicationConfig } from '@angular/core';
import { getTVChartDefaultProviders } from "ngx-lightweight-charts";
export const appConfig: ApplicationConfig = {
providers: [
// ...
getTVChartDefaultProviders()
]
};
There are two ways:
Either use the tvChart
directive, specifying the type of chart to be displayed.
<div tvChart="Line" [data]="lineData"></div>
Or use one of the following convenience components that wrap tvChart
to create a specific chart type.
<tv-area-chart [data]="pointData"></tv-area-chart>
<tv-bar-chart [data]="barData"></tv-bar-chart>
<tv-baseline-chart [data]="pointData"></tv-baseline-chart>
<tv-candlestick-chart [data]="klineData"></tv-candlestick-chart>
<tv-histogram-chart [data]="pointData"></tv-histogram-chart>
<tv-line-chart [data]="pointData"></tv-line-chart>
All charts expose the following signal based inputs and outputs:
(Generic type T
extends SeriesType and HorzItemScale
defaults to Time)
Input | type |
---|---|
id | string |
options | DeepPartial<ChartOptions> |
seriesOptions | SeriesPartialOptionsMap[T] |
data | SeriesDataItemTypeMap<HorzScaleItem>[T][] |
markers | SeriesMarker<HorzScaleItem>[] |
Output | type |
---|---|
initialised | TVChart<T, HorzScaleItem> |
chartClick | MouseEventParams<HorzScaleItem> |
chartDBLClick | MouseEventParams<HorzScaleItem> |
crosshairMoved | MouseEventParams<HorzScaleItem> |
visibleTimeRangeChanged | Range<HorzScaleItem> |
visibleLogicalRangeChanged | LogicalRange | null |
sizeChanged | number |
dataChanged | DataChangedScope |
TVChart
is the core class that creates, manages and exposes a trading view chart and its associated series.
For convenience TVChart
implements the majority of the IChartApi
interface and also exposes the IChartApi
, ITimeScaleApi
and ISeriesApi
subscriptions as RXJS streams.
It also exposes the underlying chart, timeScale, priceScale and series through accessors.
Every chart directive/component is simply a container that initialises an injected TVChart
instance and exposes
a limited set of inputs and outputs to interact with the core functionality of the chart and series.
Once a TVChart
has been initialised, there are 2 ways to access it:
1). Through the initialised
output of the chart directive/component
import {Component} from "@angular/core";
import {TVChartDirective, TVChart} from "ngx-lightweight-chart";
import {LineData} from "lightweight-charts";
@Component({
selector: 'my-component',
standalone: true,
imports: [
TVChartDirective
],
template: `
<div tvChart="Line" [data]="chartData" (initialised)="onChartInit($event)"></div>
`
})
export class MyComponent {
chartData: LineData[]
onChartInit(chart: TVChart<"Line">) {
//... perform some action through the TVChart API
}
}
2). Through the tvChartCollector
directive when creating reusable functionality, which can be used to access and interact with a single TVChart
or a collection.
The tvChartCollector
also ensures that all TVChart
instances have been fully initialised before exposing them for access through the charts
signal.
Accessing a single TVChart
instance:
<div tvChart="Line" [data]="chartData" tvChartCollector myDirective></div>
import {Directive, effect, inject} from "@angular/core";
import {TVChartCollectorDirective, TVChart} from "ngx-lightweight-charts";
@Directive({
selector: '[myDirective]',
standalone: true
})
export class MyDirective {
readonly #collector = inject(TVChartCollectorDirective);
constructor() {
effect(() => {
this.#collector.charts()?.forEach((chart: TVChart<any>) => {
//... perform some action through the TVChart API
});
});
}
}
Accessing multiple TVChart instances:
<div tvChartCollector myMultiChartDirective>
<tv-candlestick-chart [data]="klineData"></tv-candlestick-chart>
<tv-histogram-chart [data]="pointData"></tv-histogram-chart>
<tv-line-chart [data]="pointData"></tv-line-chart>
</div>
import {Directive, effect, inject} from "@angular/core";
import {TVChartCollectorDirective, TVChart} from "ngx-lightweight-charts";
@Directive({
selector: '[myMultiChartDirective]',
standalone: true
})
export class MyMultiChartDirective {
readonly #collector = inject(TVChartCollectorDirective);
constructor() {
effect(() => {
this.#collector.charts()?.forEach((chart: TVChart<any>) => {
//... perform some action through the TVChart API
});
});
}
}
You may have noticed that the implementation of MyDirective
and MyMultiChartDirective
are identical. This is intentional.
The TVChartCollectorDirective.charts
signal always returns an array of charts (whether collecting a single or multiple)
allowing the flexibility to easily implement directives or components that work with single and/or multiple charts.
The tvChartCollector
also accepts an array of id's to facilitate the filtering of charts by id:
<div [tvChartCollector]="['one, 'two']" myDirective>
<tv-candlestick-chart id="one" [data]="klineData"></tv-candlestick-chart>
<tv-histogram-chart id="two" [data]="pointData"></tv-histogram-chart>
<tv-line-chart [data]="pointData"></tv-line-chart>
</div>
import {Directive, effect, inject} from "@angular/core";
import {TVChartCollectorDirective, TVChart} from "ngx-lightweight-charts";
@Directive({
selector: '[myDirective]',
standalone: true
})
export class MyDirective {
readonly #collector = inject(TVChartCollectorDirective);
constructor() {
effect(() => {
this.#collector.charts()?.forEach((chart: TVChart<any>) => {
//... perform something only on chart "one" and "two"
});
});
}
}
The following example uses the Custom chart HLC area implementation - source code can be found here
Given the following app component:
import {Component} from "@angular/core";
@Component({
selector: 'app-root',
standalone: true,
templateUrl: './app.component.html'
})
export class AppComponent {
customSeriesView = new HLCAreaSeries();
customData = generateAlternativeCandleData(100);
}
There are 2 ways to display custom data:
1). Using the TVChartCustomSeriesComponent
<tv-custom-series-chart [data]="customData" [customSeriesView]="customSeriesView"></tv-custom-series-chart>
2). By adding an additional (custom) series to an existing chart
<div tvChart="Candlestick" [data]="customData" tvChartCollector [customSeriesExample]="customSeriesView"></div>
import {Directive, effect, inject, input} from "@angular/core";
import {TVChartCollectorDirective, TVChart} from "ngx-lightweight-charts";
import {CustomData, CustomSeriesOptions, ICustomSeriesPaneView, ISeriesApi, Time} from "lightweight-charts";
@Directive({
selector: '[customSeriesExample]',
standalone: true
})
export class CustomSeriesExampleDirective<HorzScaleItem = Time> {
readonly #collector = inject(TVChartCollectorDirective);
data = input<CustomData<HorzScaleItem>[]>();
customSeriesView = input.required<ICustomSeriesPaneView<HorzScaleItem>>({alias: 'customSeriesExample'});
seriesOptions = input<CustomSeriesOptions>({} as CustomSeriesOptions);
#series?: ISeriesApi<'Custom', HorzScaleItem>;
constructor() {
effect(() => {
this.#collector.charts()?.forEach((chart: TVChart<'Candlestick', HorzScaleItem>) => {
const data = this.data(),
customSeriesView= this.customSeriesView();
if(!data || !customSeriesView) {
return;
}
({
series: this.#series
} = chart.addAdditionalSeries('Custom', this.seriesOptions(), customSeriesView));
this.#series?.setData(data);
});
});
}
}
TVChartGroupDirective
Visually groups multiple charts
<div tvChartCollector tvChartGroup>
<tv-area-chart [data]="pointData"></tv-area-chart>
<tv-histogram-chart [data]="pointData"></tv-histogram-chart>
<tv-line-chart [data]="pointData"></tv-line-chart>
</div>
TVChartSyncDirective
Syncs the visible logical range (scale and position) and cross-hair of multiple charts
<div tvChartCollector tvChartSync>
<tv-candlestick-chart [data]="klineData"></tv-candlestick-chart>
<tv-histogram-chart [data]="pointData"></tv-histogram-chart>
</div>
TVChartCrosshairDataDirective
Outputs data relating to the current cross-hair position
Single chart:
<tv-candlestick-chart [data]="klineData" tvChartCollector (tvChartCrosshairData)="onCrosshairData($event)"></tv-candlestick-chart>
import {Component} from "@angular/core";
import {TVChartCrosshairDataDirective} from "ngx-lightweight-charts";
@Component({
selector: 'app-root',
standalone: true,
imports: [
TVChartCrosshairDataDirective
],
templateUrl: './app.component.html'
})
export class AppComponent {
onCrosshairData(data: {[key: string | number]: Record<string, any>}): void {
/*
The format of the data is as follows
{
[chart id || index]: {
// cross-hair point data
}
}
*/
// do something with data here...
}
}
Multiple charts:
<div tvChartCollector tvChartSync (tvChartCrosshairData)="onCrosshairData($event)">
<tv-candlestick-chart id="ohlc" [data]="klines" [options]="{rightPriceScale: {minimumWidth: 80}}"></tv-candlestick-chart>
<div tvChart="Histogram" [data]="rsiValues" [options]="{rightPriceScale: {minimumWidth: 80}}"></div>
</div>
import {Component} from "@angular/core";
import {OhlcData, HistogramData, Time} from "lightweight-charts";
import {TVChartCrosshairDataDirective} from "ngx-lightweight-charts";
@Component({
selector: 'app-root',
standalone: true,
imports: [
TVChartCrosshairDataDirective
],
templateUrl: './app.component.html'
})
export class AppComponent {
klines: OhlcData<Time>[] = [/* loaded kline data */];
rsiData: HistogramData<Time>[] = [/* loaded rsi data */];
onCrosshairData(data: {[key: string | number]: Record<string, any>}): void {
/*
The format of the data is as follows
{
ohlc: {
time: ...,
open: ...,
high: ...,
low: ...,
close: ...
},
2: {
time: ...,
value: ...
}
}
*/
// do something with data here...
}
}
To add your own behaviour it's as simple as doing the following:
<div tvChart="Line" [data]="chartData" tvChartCollector yourDirective></div>
import {Directive, effect, inject} from "@angular/core";
import {TVChartCollectorDirective, TVChart} from "ngx-lightweight-charts";
@Directive({
selector: '[yourDirective]',
standalone: true
})
export class YourDirective {
readonly #collector = inject(TVChartCollectorDirective);
constructor() {
effect(() => {
this.#collector.charts()?.forEach((chart: TVChart<any>) => {
//... perform some action through the TVChart API
});
});
}
}
FAQs
Angular wrapper for Trading View lightweight-charts
The npm package ngx-lightweight-charts receives a total of 7 weekly downloads. As such, ngx-lightweight-charts popularity was classified as not popular.
We found that ngx-lightweight-charts demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
ECMAScript 2025 introduces Iterator Helpers, Set methods, JSON modules, and more in its latest spec update approved by Ecma in June 2025.
Security News
A new Node.js homepage button linking to paid support for EOL versions has sparked a heated discussion among contributors and the wider community.
Research
North Korean threat actors linked to the Contagious Interview campaign return with 35 new malicious npm packages using a stealthy multi-stage malware loader.