how to update chart tradingview

I am working on a trading view chart, and in the program I am writing, there is a section that should be taken from the api by selecting a dropdown and display it on the chart.
My problem is that I get the data from the api, but the chart is not updated with the new data, please help me

main.js
// Datafeed implementation
import Datafeed from './datafeed.js';

const hashtag = decodeURIComponent(window.location.pathname);
const result = hashtag.split('/');
console.log('result:', result);

var widget = new TradingView.widget({
symbol: ${result[3]},
interval: '1h',
timeframe: '1h',
timezone: 'Asia/Tehran',
fullscreen: true,
container: 'tv_chart_container',
debug: true,
enabled_features: ['request_only_visible_range_on_reset', 'side_toolbar_in_fullscreen_mode'],
disabled_features: ['header_screenshot'],
datafeed: Datafeed,
library_path: 'advanced-chart/charting_library_cloned_data/charting_library/',
locale: 'fa',
theme: 'dark',
autosize: 'true',
custom_css_url: "css/style.css",
custom_font_family: "yekan",
custom_formatters: {
timeFormatter: {
format: (date) => {
const _format_str = '%h:%m';
return _format_str
.replace('%h', date.getUTCHours(), 2)
.replace('%m', date.getUTCMinutes(), 2)
.replace('%s', date.getUTCSeconds(), 2);
}
},
dateFormatter: {
format: (date) => {
return new Intl.DateTimeFormat("fa", { year: "numeric", month: "long", day: "2-digit", hour: '2-digit', minute: '2-digit' }).format(date);
}
},
tickMarkFormatter: (date, tickMarkType) => {
let jalaliDate = toJalali(date);
console.log('tickMarkFormatter:', { date, jalaliDate, tickMarkType });
switch (tickMarkType) {
case 'Year':
return jalaliDate.jy;
case 'Month':
return jalaliDate.jm;
case 'DayOfMonth':
return jalaliDate.jd;
case 'Time':
return jalaliDate.jh;
case 'TimeWithSeconds':
return '';
}
throw new Error('Unhandled tick mark type ' + tickMarkType);
},
priceFormatterFactory: (symbolInfo, minTick) => {
if (symbolInfo?.fractional || minTick !== 'default' && minTick.split(',')[2] === 'true') {
return {
format: (price, signPositive) => {
// return the appropriate format
},
};
}
return null;
},
studyFormatterFactory: (format, symbolInfo) => {
if (format.type === 'price') {
const numberFormat = new Intl.NumberFormat('en-US', { notation: 'scientific' });
return {
format: (value) => numberFormat.format(value)
};
}
if (format.type === 'volume') {
return {
format: (value) => (value / 1e9).toPrecision(format?.precision || 2) + 'B'
};
}
if (format.type === 'percent') {
return {
format: (value) => ${value.toPrecision(format?.precision || 4)} percent
};
}
return null;
},
}
});

widget.headerReady().then(function () {
// Create a custom button
const button = widget.createButton({
align: 'left'
});

button.setAttribute('title', 'twite');
button.className = 'custom-button';

button.innerHTML = 'send analyze'

button.addEventListener('click', async function () {
    try {
        if ($userLoggedIn === 0) {
            window.location.href = '/authentication';
            return;
        }

        $('#screenShotChart').modal('show');
        $('#screenShotChart').on('shown.bs.modal', async function () {
            const screenshotCanvas = await widget.takeClientScreenshot();
            // Convert the screenshot to a Base64 string
            const base64String = screenshotCanvas.toDataURL('image/png');
            // Log the Base64 string to the console
            console.log(base64String);
            $('#screenshotChartBase64').val(base64String);
        });
    } catch (error) {
        console.error('Error taking screenshot:', error);
    }
});

button.style.marginLeft = '10px';

});

widget.headerReady().then(function () {
widget.createDropdown({
title: 'تعدیل نمودار',
items: [
{
title: 'تعدیل شده',
onSelect: async () => {
const chart = widget.activeChart();
const symbolInfo = widget.activeChart().symbol(); // تغییر به symbolExt
const resolution = widget.activeChart().resolution();
const now = Math.floor(Date.now() / 1000); // زمان فعلی به ثانیه
const from = now - 365 * 24 * 60 * 60; // یک سال پیش

`` if (!symbolInfo || !resolution) {                     console.error('Invalid symbolInfo or resolution');                     return;                 }                   const onHistoryCallback = (bars) => {                     let series = chart.getSeries();                     if (series.length > 0) {                         // بروزرسانی داده‌های سری موجود                         series[0].setData(bars);                     } else {                         // ایجاد سری جدید و اضافه کردن داده‌ها                         const newSeries = chart.addSeries({                             type: 'candlestick',                             title: symbolInfo.name,                         });                         newSeries.setData(bars);                     }                 };                  const onErrorCallback = (error) => {                     console.error('Error fetching bars:', error);                 };                  await Datafeed.getBars(symbolInfo, resolution, from, onHistoryCallback, onErrorCallback, 1);             },         },`         {             title: 'تعدیل نشده',             onSelect: async () => {                 console.log(widget);                 const symbolInfo = widget.activeChart().symbol(); // تغییر به symbolExt                 const resolution = widget.activeChart().resolution();                 const now = Math.floor(Date.now() / 1000); // زمان فعلی به ثانیه                 const from = now - 365 * 24 * 60 * 60; // یک سال پیش                  const chart = widget.activeChart();                 const series = chart.getSeries();                 console.log(series);                 console.log(chart);                  if (!symbolInfo || !resolution) {                     console.error('Invalid symbolInfo or resolution');                     return;                 }                  const onHistoryCallback =  (bars,meta)=>{                  } ; ``

`
const onErrorCallback = (error) => {
console.error('Error fetching bars:', error);
};

                await handleDropdownSelect(symbolInfo, resolution, from, onHistoryCallback, onErrorCallback, null);


            },
        },
    ],
}).then(myDropdownApi => {
    // Dropdown API می‌توانید از myDropdownApi استفاده کنید
});

});
function toJalali(date) {
let jalaliDateFormat = new Intl.DateTimeFormat("fa", { year: "numeric", month: "long", day: "2-digit", hour: '2-digit', minute: '2-digit', second: '2-digit' });
let parts = jalaliDateFormat.formatToParts(date);
if (parts.length >= 11) {
return {
jy: parts[4].value,
jm: parts[2].value,
jd: parts[0].value,
jh: parts[6].value + parts[7].value + parts[8].value,
};
}
throw new Error('Invalid parts array length');
}

datafeed.js
import {
makeApiRequest,
generateSymbol,
parseFullSymbol,
} from './helpers.js';
import {widget} from "../charting_library_cloned_data/charting_library";

const lastBarsCache = new Map();

const configurationData = {
supported_resolutions: ['1h','4h','24h','1D','1w'],
exchanges: [
{
value: 'همه بازار ها',
name: 'عمومی',
desc: '',
},
{
value: 'بورس',
name: 'بورس',
desc: ''
},
],
symbols_types: [{
name: 'همه',
value: '0',
},
{
name: 'سهام',
value: '1',
}],
};

async function getAllSymbols() {
const data = await makeApiRequest(‘api/symbol/all’);

let allSymbols = [];
for (const exchange of configurationData.exchanges) {
    for (const leftPairPart of data) {
        allSymbols.push({
            symbol: leftPairPart.LVal18AFC,
            full_name: leftPairPart.LVal18AFC,
            description: leftPairPart.LSoc30,
            exchange: exchange.value,
            type: 'بورس',
        });
    }
}
return allSymbols;

}

export default {
onReady: (callback) => {
console.log('[onReady]: Method call');
setTimeout(() => callback(configurationData));
},

searchSymbols: async (
    userInput,
    exchange,
    symbolType,
    onResultReadyCallback,
) => {
    console.log('[searchSymbols]: Method call');
    const symbols = await getAllSymbols();
    const newSymbols = symbols.filter(symbol => {
        const isExchangeValid = exchange === 'همه بازار ها' || symbol.exchange === exchange;
        const isFullSymbolContainsInput = symbol.full_name && symbol.full_name.indexOf(userInput) !== -1;
        return isExchangeValid && isFullSymbolContainsInput;
    });
    onResultReadyCallback(newSymbols);
},
resolveSymbol: async (
    symbolName,
    onSymbolResolvedCallback,
    onResolveErrorCallback,
    extension
) => {
    console.log('[resolveSymbol]: Method call', symbolName);
    const symbols = await getAllSymbols();
    const symbolItem = symbols.find(({ full_name }) => full_name === symbolName);
    if (!symbolItem) {
        console.log('[resolveSymbol]: Cannot resolve symbol', symbolName);
        onResolveErrorCallback('cannot resolve symbol');
        return;
    }
    const symbolInfo = {
        ticker: symbolItem.full_name,
        name: symbolItem.symbol,
        description: symbolItem.description,
        type: symbolItem.type,
        session: '24x7',
        timezone: 'Asia/Tehran',
        exchange: symbolItem.exchange,
        minmov: 1,
        pricescale: 100,
        has_intraday: true,
        has_daily: true,
        intraday_multipliers: ['60','240','1440'],
        has_weekly_and_monthly: false,
        supported_resolutions: configurationData.supported_resolutions,
        volume_precision: 2,
        data_status: 'streaming',
    };
    console.log('[resolveSymbol]: Symbol resolved', symbolName);
    onSymbolResolvedCallback(symbolInfo);
},
getBars: async (symbolInfo, resolution, from, onHistoryCallback,onErrorCallback, isTadil = null) => {
    if (!symbolInfo || !resolution) {
        console.error('[getBars]: Invalid symbolInfo or resolution');
        onErrorCallback('Invalid symbolInfo or resolution');
        return;
    }

    try {


        const hashtag = decodeURIComponent(window.location.pathname);
        const result = hashtag.split('/');
        console.log(symbolInfo.name)
      if(symbolInfo.name!==result[3]  && symbolInfo.name!=undefined)
      {
          window.location.href=`http://127.0.0.1:8000/twitter/hashtag/${symbolInfo.name}`
      }


        const apiUrl = isTadil !== null ? `/api/symbol/${symbolInfo}/tadil` : `/api/symbol/${symbolInfo.name}`;
        const res = await fetch(apiUrl);

        console.log(isTadil,apiUrl);

        if (!res.ok) {
            throw new Error('Network response was not ok');
        }

        const data = await res.json();

        if (!Array.isArray(data)) {
            throw new Error('Data format is incorrect');
        }

        console.log('Received data:', data);

        let bars = data.map(bar => {
            let timestamp = bar.jdates && bar.jdates.$date && bar.jdates.$date.$numberLong
                ? parseInt(bar.jdates.$date.$numberLong) : null;

            if (!isNaN(timestamp)) {
                return {
                    time: timestamp,
                    open: parseFloat(bar.open),
                    high: parseFloat(bar.high),
                    low: parseFloat(bar.low),
                    close: parseFloat(bar.close),
                    volume: parseFloat(bar.volume, 10),
                    isBarClosed: true,
                    isLastBar: false,
                };
            } else {
                console.log(`Invalid date for bar: ${JSON.stringify(bar)}`);
                return null;
            }
        });

        const filteredBars = bars.filter(bar => bar && bar.time !== null && bar.time !== undefined );

        if (resolution === '1D') {
            if (filteredBars.length > 0) {
                bars = convertIntradayToDaily(filteredBars, lastBarsCache.get(symbolInfo.name) || []);
            } else {
                bars = [];
            }
        } else {
            bars = filteredBars;
        }

        const uniqueBars = Array.from(new Set(bars.map(bar => bar.time)))
            .map(time => {
                return bars.find(bar => bar.time === time);
            });

        uniqueBars.sort((a, b) => a.time - b.time);

        const finalBars = [];
        let lastTime = null;

        for (const bar of uniqueBars) {
            if (lastTime === null || bar.time > lastTime) {
                finalBars.push(bar);
                lastTime = bar.time;
            } else {
                console.log(`Skipped duplicate or out-of-order bar: ${bar.time}`);
            }
        }

        console.log('Filtered and Sorted Bars:', finalBars);
        console.log(`[getBars]: returned ${finalBars.length} bar(s)`);

        onHistoryCallback(finalBars, {
            noData: finalBars.length === 0,
        });
    } catch (error) {
        console.log('[getBars]: Get error', error);
        onErrorCallback(error);
    }



},
subscribeBars: (symbolInfo, resolution, onRealtimeCallback, subscriberUID, onResetCacheNeededCallback) => {
    console.log('[subscribeBars]: Method call with:', { symbolInfo, resolution, subscriberUID });

    // Add your subscription logic here
    // Store the subscription data in the lastBarsCache or any other state management
},

unsubscribeBars: (subscriberUID) => {
    console.log('[unsubscribeBars]: Method call with:', { subscriberUID });

    // Add your unsubscription logic here
    // Remove the subscription data from the lastBarsCache or any other state management
},

};

function convertIntradayToDaily(intradayData, cachedData) {
const getTimeRange = (data) => {
if (data.length === 0) return { start: null, end: null };
const start = new Date(data[0].time);
const end = new Date(data[data.length - 1].time);
return { start, end };
}

const newTimeRange = getTimeRange(intradayData);
const cachedTimeRange = getTimeRange(cachedData);

if (newTimeRange.start && cachedTimeRange.start &&
    newTimeRange.start.getTime() === cachedTimeRange.start.getTime() &&
    newTimeRange.end.getTime() === cachedTimeRange.end.getTime()) {
    console.log('Time range of received data is the same as cached one. Skip the update.');
    return cachedData;
}

const dailyData = [];
let dailyCandle = null;
let currentDay = null;

intradayData.forEach(candle => {
    const date = new Date(candle.time);
    const day = date.toISOString().split('T')[0];

    if (currentDay !== day) {
        if (dailyCandle) {
            dailyData.push(dailyCandle);
        }
        currentDay = day;
        dailyCandle = {
            time: date.getTime(),
            open: candle.open,
            high: candle.high,
            low: candle.low,
            close: candle.close,
            volume: candle.volume
        };
    } else {
        dailyCandle.high = Math.max(dailyCandle.high, candle.high);
        dailyCandle.low = Math.min(dailyCandle.low, candle.low);
        dailyCandle.close = candle.close;
        dailyCandle.volume += candle.volume;
    }
});

if (dailyCandle) {
    dailyData.push(dailyCandle);
}

return dailyData;

}

I expected the chart to update but it didn’t

New contributor

Sajad Khosravi is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật