Skip to main content

Using widgets with Vue

In this tutorial, you'll learn how to easily integrate widgets into Vue, using the WatchList widget as an example. Let's create a simple widget component.

Simple widget

Let's create a component of watch list widget as basic example:

<script setup>
import { newWatchListWidget } from '@dxfeed-widgets/watch-list'
import { onMounted, onUnmounted, ref, watchEffect } from 'vue'

const dataProviders = {
ipfPath: '/your-path/ipf',
ipfAuthHeader: 'your-header',
feedPath: 'wss://your-path/feed',
feedAuthHeader: 'your-header',
fundamentalsPath: '/api/fundamentals',
fundamentalsAuthHeader: 'your-header',
schedulePath: '/api/schedule',
}

const element = ref()
let widget
onMounted(() => {
widget = newWatchListWidget({
element: element.value,
providers: dataProviders,
config: { dataExportEnabled: true }
state: {
symbols: [],
selectedSymbol: undefined,
columns: ['symbol', 'lastPrice'],
columnSizes: {},
filters: {},
sort: undefined,
}
})
})

onUnmounted(() => {
widget?.unmount()
})
</script>

<template>
<div ref="element" style="height: 100%; width: 100%" />
</template>

Connecting widgets

Using standalone widget is a possible way to use library, but let's make something more complex and create a connection between two widgets.

Firstly, we need to establish a shareable state. As an example, we can connect widgets by symbol. In this case, our app will appear as follows:

<script setup>
import { ref } from 'vue'
import WatchList from './WatchList.vue'

const selectedSymbol$ = ref(undefined)
function onSelectedSymbol(value) {
selectedSymbol$.value = value
}
</script>

<template>
<WatchList @selected-symbol="onSelectedSymbol" />
</template>

We provide some state on the top level of our application. Let's now adjust our simple component and create one more widget to facilitate the passing of widget state.

<!-- WatchList.vue -->
<script setup>
import { newWatchListWidget } from '@dxfeed-widgets/watch-list'
import { defineEmits, onMounted, onUnmounted, ref } from 'vue'
import { dataProviders } from './dataProviders'

const emit = defineEmits<{
selectedSymbol: [string | undefined]
}>()

onMounted(() => {
widget = newWatchListWidget({
element: element.value,
providers: dataProviders,
config: { dataExportEnabled: true }
state: {
symbols: [],
selectedSymbol: undefined,
columns: ['symbol', 'lastPrice'],
columnSizes: {},
filters: {},
sort: undefined,
}
})

widget.addStateListener('selectedSymbol', symbol => {
emit('selectedSymbol', symbol)
})
})

onUnmounted(() => {
widget?.unmount()
})
</script>

<template>
<div ref="element" style="height: 100%; width: 100%" />
</template>
<!-- TimeAndSales.vue -->
<script setup>
import { newTimeAndSalesWidget } from '@dxfeed-widgets/time-and-sales'
import { defineProps, onMounted, onUnmounted, ref, toRefs, watchEffect } from 'vue'
import { dataProviders } from './dataProviders'

const props = defineProps<{
symbol: string | undefined
}>()
const props$ = toRefs(props)

onMounted(() => {
widget = newTimeAndSalesWidget({
element: element.value,
providers: dataProviders,
state: {
symbol: props$.symbol
}
})
})

watchEffect(() => {
const symbol = props$.symbol
widget?.updateState({ symbol })
})

onUnmounted(() => {
widget?.unmount()
})
</script>

<template>
<div ref="element" style="height: 100%; width: 100%" />
</template>

Now we can provide this data to another component or widget the following way:

<script setup>
import { ref } from 'vue'
import WatchList from './WatchList.vue'
import TimeAndSales from './TimeAndSales.vue'
import AnyAnotherComponent from './AnyAnotherComponent.vue'

const selectedSymbol$ = ref(undefined)
function onSelectedSymbol(value) {
selectedSymbol$.value = value
}
</script>

<template>
<WatchList @selected-symbol="onSelectedSymbol" />
<TimeAndSales :symbol="selectedSymbol$" />
<AnyAnotherComponent :symbol="selectedSymbol$" />
</template>