DocumentationFramework Integration

Framework integration

OpenAlgo Charts is a framework-agnostic vanilla library. You call createChart(container) with a DOM element and get back a Chart instance. Every framework wrapper follows the same two-step pattern: create in the mount hook, destroy in the teardown hook.

The chart attaches a built-in ResizeObserver to its container on construction, so it reflows automatically whenever the container changes size.

The built-in ResizeObserver handles responsive resize automatically. You do not need to wire a window resize listener. Call chart.applySize(width, height) only in environments that lack ResizeObserver support, or when you need to drive the chart size imperatively.

Install

npm install openalgo-charts
import { createChart, generateBars } from 'openalgo-charts';

generateBars(startTimeSec, count, intervalSec) produces a seeded synthetic OHLCV walk useful for prototyping. Replace it with real bar data before going to production.

Vanilla JavaScript

<div id="chart" style="width: 100%; height: 400px;"></div>
import { createChart, generateBars } from 'openalgo-charts';
 
const container = document.getElementById('chart');
const chart = createChart(container);
 
const series = chart.addSeries('candlestick');
series.setData(generateBars(1700000000, 120, 3600));
 
// When removing the chart from the page:
chart.destroy();

destroy() stops the render loop, disconnects the ResizeObserver, removes all input listeners, and detaches every canvas from the DOM.

React

Keep the chart in a useRef so it persists across re-renders. Create it inside useEffect (which is client-only) and return the cleanup function so React calls destroy() on unmount.

import { useEffect, useRef } from 'react';
import { createChart, generateBars } from 'openalgo-charts';
import type { Chart } from 'openalgo-charts';
 
export function CandlestickChart() {
  const containerRef = useRef<HTMLDivElement>(null);
  const chartRef = useRef<Chart | null>(null);
 
  useEffect(() => {
    if (!containerRef.current) return;
 
    const chart = createChart(containerRef.current);
    chartRef.current = chart;
 
    const series = chart.addSeries('candlestick');
    series.setData(generateBars(1700000000, 120, 3600));
 
    return () => {
      chart.destroy();
      chartRef.current = null;
    };
  }, []); // empty deps: create once on mount, destroy on unmount
 
  return <div ref={containerRef} style={{ width: '100%', height: 400 }} />;
}

Do not call createChart in the component body or inside a useMemo. Canvas creation requires a real DOM node, which only exists after the first render.

Next.js / SSR

createChart touches the DOM immediately and must never run on the server. There are two safe approaches.

Option 1 - useEffect (simplest). useEffect never runs during server-side rendering, so the React example above works in Next.js without any changes.

Option 2 - dynamic import with ssr: false. Use this when you want to ship the chart component as its own async chunk or need to suppress the hydration mismatch warning:

// components/Chart.tsx
import { useEffect, useRef } from 'react';
import { createChart, generateBars } from 'openalgo-charts';
 
export default function Chart() {
  const containerRef = useRef<HTMLDivElement>(null);
 
  useEffect(() => {
    if (!containerRef.current) return;
    const chart = createChart(containerRef.current);
    const series = chart.addSeries('candlestick');
    series.setData(generateBars(1700000000, 120, 3600));
    return () => chart.destroy();
  }, []);
 
  return <div ref={containerRef} style={{ width: '100%', height: 400 }} />;
}
// app/page.tsx  (or pages/index.tsx)
import dynamic from 'next/dynamic';
 
const Chart = dynamic(() => import('../components/Chart'), { ssr: false });
 
export default function Page() {
  return <Chart />;
}

The ssr: false flag tells Next.js to skip the component entirely during server rendering and hydrate it on the client only.

Vue 3

Use a template ref with onMounted to create and onUnmounted to destroy.

<template>
  <div ref="containerRef" style="width: 100%; height: 400px;" />
</template>
 
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { createChart, generateBars } from 'openalgo-charts';
import type { Chart } from 'openalgo-charts';
 
const containerRef = ref<HTMLDivElement | null>(null);
let chart: Chart | null = null;
 
onMounted(() => {
  if (!containerRef.value) return;
  chart = createChart(containerRef.value);
  const series = chart.addSeries('candlestick');
  series.setData(generateBars(1700000000, 120, 3600));
});
 
onUnmounted(() => {
  chart?.destroy();
  chart = null;
});
</script>

Angular

Use @ViewChild to get the container element, ngAfterViewInit to create the chart, and ngOnDestroy to tear it down.

import {
  Component, AfterViewInit, OnDestroy,
  ElementRef, ViewChild,
} from '@angular/core';
import { createChart, generateBars } from 'openalgo-charts';
import type { Chart } from 'openalgo-charts';
 
@Component({
  selector: 'app-chart',
  template: '<div #chartContainer style="width: 100%; height: 400px;"></div>',
})
export class ChartComponent implements AfterViewInit, OnDestroy {
  @ViewChild('chartContainer') containerRef!: ElementRef<HTMLDivElement>;
  private chart: Chart | null = null;
 
  ngAfterViewInit(): void {
    this.chart = createChart(this.containerRef.nativeElement);
    const series = this.chart.addSeries('candlestick');
    series.setData(generateBars(1700000000, 120, 3600));
  }
 
  ngOnDestroy(): void {
    this.chart?.destroy();
    this.chart = null;
  }
}

Svelte

onMount accepts a cleanup function. Return a function that calls chart.destroy() and Svelte will invoke it when the component is removed from the DOM.

<script lang="ts">
  import { onMount } from 'svelte';
  import { createChart, generateBars } from 'openalgo-charts';
 
  let containerEl: HTMLDivElement;
 
  onMount(() => {
    const chart = createChart(containerEl);
    const series = chart.addSeries('candlestick');
    series.setData(generateBars(1700000000, 120, 3600));
 
    return () => chart.destroy();
  });
</script>
 
<div bind:this={containerEl} style="width: 100%; height: 400px;" />