ehsan-shv/vue-tradingviewWidgets

Symbol with dynamic value

Closed this issue · 11 comments

Hi dear friend
I used this service and set the symbol value dynamically
But after changing the name of the currency, the chart is not updated to be loaded with the new currency
I even used several methods to reload the component manually after changing the name of the currency, but unfortunately it did not work.
Can you help me to solve my problem?

Hi! Would you give me a code demo here?

Hi! Would you give me a code demo here?

const currencyName = ref('')

const Option = computed(() => ({
width: '88vw',
height: '500',
symbol: currencyName,
interval: '60',
style: '1',
locale: 'en',
enable_publishing: false,
allow_symbol_change: true,
theme: 'dark'
}))

<Chart

      class="d-flex flex-row justify-content-center"
      :options="Option"

/>

*currencyName value is filled from the api

key may helps you:
<Chart :key="Option.symbol" class="d-flex flex-row justify-content-center" :options="Option" />

I used this method
but after choosing a new currency, it does not show the chart at all

same problem here.
I am facing same problem

I managed to fix this by copying src/components/Chart.vue into my project and removing if (scriptExists()) return, which prevented from re-rendering.

Here is the component you can copy and paste into your project:

<template>
	<div :id="container" />
</template>

<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue'

declare global {
  interface Window {
    TradingView: any;
  }
}
window.TradingView = window.TradingView || {}
export default defineComponent({
	name: 'Chart',
	props: {
		options: {
			type: Object,
			default: () => ({}),
		},
	},
	setup(props) {
		const container = ref('tradingview-chart')
		const scriptID = ref('tradingview-chart-script')

		const defualtOptions = {
			width: 980,
			height: 610,
			symbol: 'NASDAQ:AAPL',
			interval: 'D',
			timezone: 'Etc/UTC',
			theme: 'light',
			style: '1',
			locale: 'en',
			toolbar_bg: '#f1f3f6',
			enable_publishing: false,
			allow_symbol_change: true,
			container_id: 'tradingview-chart',
		}

		const canUseDOM = () => {
			return typeof window !== 'undefined' && window.document && window.document.createElement
		}
		
		const getScriptElement = () => {
			return document.getElementById(scriptID.value)
		}
		
		// const scriptExists = () => {
		// 	return getScriptElement() !== null
		// }
		
		const appendScript = (onload: () => void) => {
			if (!canUseDOM()) return
			// if (scriptExists()) return

			const script = document.createElement('script')
			script.id = scriptID.value
			script.type = 'text/javascript'
			script.async = true
			script.src = 'https://s3.tradingview.com/tv.js'
			script.onload = onload
			document.getElementsByTagName('head')[0].appendChild(script)
		}


		
		const initWidget = () => {
			setTimeout(() => {
				if (typeof window.TradingView === 'undefined') return
				const options: { container_id: string } = { ...defualtOptions, ...props.options }
				if (options.container_id !== container.value) {
					console.error('container_id in Chart component must be "tradingview-chart"')
					return
				}
				new window.TradingView.widget(Object.assign({ container_id: container }, options))
			}, 300)
		}
		
		onMounted(() => {
			appendScript(() => initWidget())
		})
		return { container }
	},
})
</script>

I am pretty sure there is a better way to fix this. I may take a look at it later.

I managed to fix this by copying src/components/Chart.vue into my project and removing if (scriptExists()) return, which prevented from re-rendering.

Here is the component you can copy and paste into your project:

<template>
	<div :id="container" />
</template>

<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue'

declare global {
  interface Window {
    TradingView: any;
  }
}
window.TradingView = window.TradingView || {}
export default defineComponent({
	name: 'Chart',
	props: {
		options: {
			type: Object,
			default: () => ({}),
		},
	},
	setup(props) {
		const container = ref('tradingview-chart')
		const scriptID = ref('tradingview-chart-script')

		const defualtOptions = {
			width: 980,
			height: 610,
			symbol: 'NASDAQ:AAPL',
			interval: 'D',
			timezone: 'Etc/UTC',
			theme: 'light',
			style: '1',
			locale: 'en',
			toolbar_bg: '#f1f3f6',
			enable_publishing: false,
			allow_symbol_change: true,
			container_id: 'tradingview-chart',
		}

		const canUseDOM = () => {
			return typeof window !== 'undefined' && window.document && window.document.createElement
		}
		
		const getScriptElement = () => {
			return document.getElementById(scriptID.value)
		}
		
		// const scriptExists = () => {
		// 	return getScriptElement() !== null
		// }
		
		const appendScript = (onload: () => void) => {
			if (!canUseDOM()) return
			// if (scriptExists()) return

			const script = document.createElement('script')
			script.id = scriptID.value
			script.type = 'text/javascript'
			script.async = true
			script.src = 'https://s3.tradingview.com/tv.js'
			script.onload = onload
			document.getElementsByTagName('head')[0].appendChild(script)
		}


		
		const initWidget = () => {
			setTimeout(() => {
				if (typeof window.TradingView === 'undefined') return
				const options: { container_id: string } = { ...defualtOptions, ...props.options }
				if (options.container_id !== container.value) {
					console.error('container_id in Chart component must be "tradingview-chart"')
					return
				}
				new window.TradingView.widget(Object.assign({ container_id: container }, options))
			}, 300)
		}
		
		onMounted(() => {
			appendScript(() => initWidget())
		})
		return { container }
	},
})
</script>

I am pretty sure there is a better way to fix this. I may take a look at it later.

I think watching the props with watch() will fix the issue. I'm gonna refactor the whole code base and fix this issue

@ehsan-shv Yeah that was one of my thoughts. Are you about to implement it this week, or later? I am thinking about contributing to this project and this seems something I can handle.

@ehsan-shv Yeah that was one of my thoughts. Are you about to implement it this week, or later? I am thinking about contributing to this project and this seems something I can handle.

I'm thinking about using Vite for packaging the components for NPM and it takes time. if you are interested in contributing to and refactoring the project, please send your Discord account to my Email then we can discuss refactoring in detail.

I've just checked and dynamic props worked in the latest version. So just install the latest version. Also, this example may help.

If there is an issue with dynamic props please reopen the issue.