Creating Tradingview Charting Library with Next JS

Gagah Kharismanuary
3 min readMar 14, 2024

--

Tradingview in Local

The Charting Library offers robust functionality for showcasing financial charts, providing a dynamic visualization tool for your website or application.

TradingView has adeptly crafted this charting library in pure JavaScript, ensuring seamless integration with your own API.
https://github.com/tradingview/charting-library-tutorial.

In this article we want to integrate the charting library with Next.JS, it may be confusing but the TradingView Team has a sample for integrating with Next.js. Here is the sample that provided from TradingView:
https://github.com/tradingview/charting-library-examples/tree/master/nextjs

Prior to starting, it’s important to mention that although the Charting Library is free to use, its source code resides within a private GitHub repository. Ensuring access to this repository is crucial for successful implementation. You can find the repository at https://github.com/tradingview/charting_library/

If you encounter a 404 error page, kindly request access to the repository via https://www.tradingview.com/advanced-charts/ and click on the “Get Library” button.

Tradingview Advanced Charts

To integrate it into a Next.js Project, we need to ensure that the Charting Library folder is placed in specific paths within our project directory: public/static.

The advantage of using Next.js instead is to use react. The Charting Library needs to be put in two places in src and public. It is confusing and while it may seem redundant to duplicate the folder in two locations, this is necessary due to the workings of React and Webpack. When operating in Next only specific in public/static.

We don’t need put anything like this one in _document.tsx, because in next.js it imported in index.tsx

<script type="text/javascript" src="/charting_library/charting_library.js"></script>

We Can Focus in our source code in pages/index.tsx

import Head from "next/head";
import dynamic from "next/dynamic";
import { useState } from "react";
import Script from "next/script";

import {
ChartingLibraryWidgetOptions,
ResolutionString,
} from "@/public/static/charting_library/charting_library";

const defaultWidgetProps: Partial<ChartingLibraryWidgetOptions> = {
symbol: "AAPL",
interval: "D" as ResolutionString,
library_path: "/static/charting_library/",
locale: "en",
charts_storage_url: "https://saveload.tradingview.com",
charts_storage_api_version: "1.1",
client_id: "tradingview.com",
user_id: "public_user_id",
fullscreen: false,
autosize: true,
};

const TVChartContainer = dynamic(
() =>
import("@/components/TVChartContainer").then((mod) => mod.TVChartContainer),
{ ssr: false }
);

export default function Home() {
const [isScriptReady, setIsScriptReady] = useState(false);
return (
<>
<Head>
<title>Sample Demo TradingView with NextJS</title>
</Head>
<Script
src="/static/datafeeds/udf/dist/bundle.js"
strategy="lazyOnload"
onReady={() => {
setIsScriptReady(true);
}}
/>
{isScriptReady && <TVChartContainer {...defaultWidgetProps} />}
</>
);
}

The script has been successfully created within our component.

import styles from "./index.module.css";
import { useEffect, useRef } from "react";
import { ChartingLibraryWidgetOptions, LanguageCode, ResolutionString, widget } from "@/public/static/charting_library";

export const TVChartContainer = (props: Partial<ChartingLibraryWidgetOptions>) => {
const chartContainerRef =
useRef<HTMLDivElement>() as React.MutableRefObject<HTMLInputElement>;

useEffect(() => {
const widgetOptions: ChartingLibraryWidgetOptions = {
symbol: props.symbol,
// BEWARE: no trailing slash is expected in feed URL
datafeed: new (window as any).Datafeeds.UDFCompatibleDatafeed(
"https://demo_feed.tradingview.com",
undefined,
{
maxResponseLength: 1000,
expectedOrder: "latestFirst",
}
),
interval: props.interval as ResolutionString,
container: chartContainerRef.current,
library_path: props.library_path,
locale: props.locale as LanguageCode,
disabled_features: ["use_localstorage_for_settings", 'header_resolutions'],
enabled_features: [],
charts_storage_url: props.charts_storage_url,
charts_storage_api_version: props.charts_storage_api_version,
client_id: props.client_id,
user_id: props.user_id,
fullscreen: props.fullscreen,
autosize: props.autosize,
theme: 'dark',
timezone: 'Asia/Bangkok',
// debug: true,
};

const tvWidget = new widget(widgetOptions);

tvWidget.onChartReady(() => {
tvWidget.headerReady().then(() => {;
const button = tvWidget.createButton();
button.setAttribute("title", "Click to show a notification popup");
button.classList.add("apply-common-tooltip");
button.addEventListener("click", () =>
tvWidget.showNoticeDialog({
title: "Notification",
body: "TradingView Charting Library API works correctly",
callback: () => {
console.log("Noticed!");
},
})
);
button.innerHTML = "Check API";
});
});

return () => {
tvWidget.remove();
};
}, [props]);

return (
<>
<div ref={chartContainerRef} className={styles.TVChartContainer} />
</>
);
};

You can find the complete implementation in my GitHub repo:
https://github.com/gagahkharismanuary/next-tradingview

For Demo Link:
https://main--next-tradingview.netlify.app/

Cheers 🚀

--

--