I am using Vue-chartjs to create a bar graph in Vue 3:
The bars are vertical. How do I make them horizontal?
<template>
<Bar
id="my-chart-id"
:options="chartOptions"
:data="chartData"
/>
</template>
<script>
import { Bar } from 'vue-chartjs'
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
export default {
name: 'BarChart',
components: { Bar },
data() {
return {
chartData: {
labels: [ 'January', 'February', 'March' ],
datasets: [ { data: [40, 20, 12] } ]
},
chartOptions: {
responsive: true
}
}
}
}
</script>
Set the indexAxis property.
<template>
<Bar
id="my-chart-id"
:options="chartOptions"
:data="chartData"
/>
</template>
<script>
import { Bar } from 'vue-chartjs'
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
export default {
name: 'BarChart',
components: { Bar },
data() {
return {
chartData: {
labels: [ 'January', 'February', 'March' ],
datasets: [ { data: [40, 20, 12] } ]
},
chartOptions: {
responsive: true,
indexAxis: 'y'
}
}
}
}
</script>
When using a library, you can check their documentation to find out more.
Then you would have found the props table;
which says:
"options: The options object that is passed into the Chart.js chart".
You know that vue-chartjs is a Vue wrapper library for the Chart.js library. Therefore, you go to their documentation. Then you go to the Chart Types part and find your chart type (Bar Chart). If you scroll down a bit you find the options for Bar Charts. The obvious one that stands out to me is the indexAxis - and in fact - it works.
Demo: here
Related
I am trying to use chartjs-plugin-zoom to implement zooming on a chart using vue-chartjs. With the code below, I get a this.$refs.myChart.resetZoom is not a function error. How do I correctly get a reference to the chart so that I can call the resetZoom function?
<template>
<div>
<button #click="resetGraph">Reset</button>
<Bar
id="myChart"
ref="myChart"
:options="chartOptions"
:data="chartData"
/>
</div>
</template>
<script>
import { Bar } from 'vue-chartjs'
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
import zoomPlugin from 'chartjs-plugin-zoom';
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, zoomPlugin)
export default {
name: 'BarChart',
components: { Bar },
data() {
return {
chartData: {
labels: [ 'January', 'February', 'March' ],
datasets: [ { data: [40, 20, 12] } ]
},
chartOptions: {
responsive: true,
indexAxis: 'y',
plugins: {
zoom: {
zoom: {
wheel: {
enabled: true,
},
pinch: {
enabled: true
},
mode: 'xy',
}
}
}
}
}
},
methods: {
resetGraph() {
this.$refs.myChart.resetZoom()
}
}
}
</script>
Changing this.$refs.myChart.resetZoom() to this.$refs.myChart.chart.resetZoom() fixed the issue for me.
I am trying to use vue-chartjs but implement it with composition api. Most examples are either in typescript which I am not familiar with or using options api. I am unable to get chartOptions to work. I am not sure if I should be removing the chart-options and just do options or if there is something else I am missing such as an import. I tried to import ChartOptions in the chart-js import statement but it draws an error. Any help on how to implement this would be very helpful. Thanks!
<template>
<Pie
:chart-options="chartOptions"
:chart-data="chartData"
:chart-id="chartId"
:dataset-id-key="datasetIdKey"
:plugins="plugins"
:css-classes="cssClasses"
:styles="styles"
:width="width"
:height="height"
/>
</template>
<script>
import {ref, defineComponent, onMounted} from 'vue'
import {Pie} from 'vue-chartjs'
import {Chart as ChartJS, Title, Tooltip, Legend, ArcElement, CategoryScale} from 'chart.js'
ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale)
export default defineComponent({
name: 'SectorPieChart',
components: { Pie },
props: {
chartId: {
type: String,
default: 'pie-chart'
},
datasetIdKey: {
type: String,
default: 'label'
},
width: {
type: Number,
default: 500
},
height: {
type: Number,
default: 500
},
cssClasses: {
default: '',
type: String
},
styles: {
type: Object,
default: () => {}
},
plugins: {
type: Object,
default: () => {}
}
},
setup() {
//stores
const portfolioStore = usePortfolioStore()
const {portfolio} = storeToRefs(portfolioStore)
//dataset
const chartData = ref({
labels: [ 'Basic Materials', 'Consumer Cyclical', 'Financial Services', 'Real Estate', 'Consumer Defensive', 'Healthcare', 'Utilities', 'Communication Services', 'Energy', 'Industrials', 'Technology'],
datasets: [
{
backgroundColor: ['#FF4A4A','#FFAC4A','#FFE9C9','#F9C87C','#F97432','#7a7979','#FFCC00','#FF9900','#86370e','#FFFF66','#ed9e67'],
data: [1,1,1,1,1,1,1,1,1,1,1]
},
{
backgroundColor: ['#FF4A4A','#FFAC4A','#FFE9C9','#F9C87C','#F97432','#7a7979','#FFCC00','#FF9900','#86370e','#FFFF66','#ed9e67'],
data: [1,1,1,1,1,1,1,1,1,1,1]
}
]
})
//chart options to change settings
const chartOptions = ref({
responsive: true,
maintainAspectRatio: true,
legend: {
display: false,
}
})
//methods
const loadData = () => {
}
//add on mount API request
onMounted(() => {
loadData()
})
return {
chartData, chartOptions, loadData
}
}
})
</script>
According to the vue-chartjs there is no ChartOptions object/function that you can import. You're just meant to create your own array of options and bind it to the :chart-options prop, exactly how you're doing already.
In order to properly set chart options you should follow the chart.js documentation. As the documentation there notes, the legend options are namespaced as options.plugins.legend, and includes boolean property display that can turn off the legend display. This means we should format our chart options like so:
const chartOptions = ref({
responsive: true,
maintainAspectRatio: true,
plugins: {
legend: {
display: false,
},
},
});
See codesandbox here.
I've added tooltips.backgroundColor in chartOptions but still doesn't work, so anyone can help me?
Here is my code
<template>
<Doughnut
:chart-options="chartOptions"
:chart-data="chartData"
:chart-id="'doughnut-chart'"
:styles="styles"
:width="width"
:height="height"
/>
</template>
<script lang="ts">
import { defineComponent, type PropType } from "vue";
import TypographyComponent from "#/core/ui/components/typography/Typography.component.vue";
import { Doughnut } from "vue-chartjs";
import {
Chart as ChartJS,
Title,
Tooltip,
Legend,
ArcElement,
CategoryScale,
type Plugin,
} from "chart.js";
ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale);
export default defineComponent({
name: "ProgressChartComponent",
components: { Doughnut, TypographyComponent },
props: {
width: {
type: Number,
default: 400,
},
height: {
type: Number,
default: 400,
},
styles: {
type: Object as PropType<Partial<CSSStyleDeclaration>>,
default: () => {},
},
chartData: {
type: Object,
required: false,
default: () => {},
},
},
setup() {
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
cutout: "64%",
tooltips: {
enabled: false,
backgroundColor: "#227799",
},
};
return {
chartOptions,
};
},
});
</script>
...
Guessing that you're using Chart.js v3, be aware that the tooltips are defined in the namespace options.plugins.tooltip but not options.tooltips as in your code. Therefore chartOptions needs to be changed as follows:
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
cutout: "64%",
plugins: {
tooltip: {
backgroundColor: "#227799"
}
}
};
For further information, please consult Tooltip Configuration from the Chart.js documentation.
I am trying to render components dynamically within my child component named ChildTabs. I would like to render the components based on the array that passed into the component from the parent view named Contatcs.
So for example if I pass the the form_type from the contact_type named "Big" it would render on my tabs vue. However I have other data that contains more than one component I am trying to render, such as medium which contains multiple forms such as Red Green & Blue.
I have an idea of creating a for loop in my method using the prop data form_type, so I can retrieve my list of forms I am trying to call, but that is where I do not know what to do next. I am already importing the forms, I am not sure how to render them.
Any suggestions are welcomed.
Contacts.vue
<template>
<div class="row">
<ChildTabs
:form_type="contact_types"
/>
</div>
</template>
<script>
'use strict';
import ChildTabs from '../tabs';
export default {
name: 'contacts-view',
data: function () {
return {
form_data: {},
failed_validations: [],
contact_type: '',
contact_types: [
{
label: 'Big',
value: 'big',
form_type: [
'Red'
]
},
{
label: 'Medium',
value: 'medium',
form_type: [
'Red',
'Green',
'Blue'
]
},
{
label: 'Small',
value: 'small',
form_type: [
'Blue',
'Green'
]
},
],
}
},
props: {
},
computed: {
},
methods: {
},
components: {
ChildTabs
}
}
</script>
Tabs.vue
<template>
<!--=============================================================-->
<!-- Contact Forms -->
<!--=============================================================-->
</template>
<script>
'use strict';
import Red from './forms/red';
import Green from './forms/green';
import Blue from './forms/blue';
export default {
name: 'forms-tab',
data: function () {
return {
}
},
props: {
form_type: {
type: Array,
required: false,
default: []
},
},
computed: {
},
methods: {
RenderComponent: function ()
{
this.$props.form_type
}
},
created: function () {
this.RenderComponent();
},
components: {
Red,
Blue,
Green
}
}
</script>
You can use dynamic component in Vue
<template>
<div>
<div v-for="type in form_type" :key="type">
<component :is="getCompentName(type)"/>
</div>
</div>
</template>
<script>
export default {
...
methods: {
getCompentName(type) {
switch (type) {
case 'red':
return 'red'
case 'blue':
return 'blue'
case 'green':
return 'green'
default:
return 'red'
}
}
}
}
</script>
Linechart.js
import { Line } from 'vue-chartjs'
export default {
extends: Line,
props:['chart']
mounted () {
this.renderChart({
labels: ['1','2','3','4','5','6','7'],
datasets: [
{
label: 'Data One',
backgroundColor: '#F64A32',
data: this.chart
}
]
}, {responsive: true, maintainAspectRatio: false})
}
}
I use the props to pass the data
example.vue
<template>
<line-chart :width="370" :height="246" :chart="chartdata"></line-chart>
</template>
<script>
import LineChart from './vue-chartjs/LineChart'
export default {
components: {
LineChart
},
},
data(){
return{
chartdata:[]
}
}
methods:{
getdata(){
this.chartdata=[10,20,30,40,50]
}
}
</script>
when I click the getdata() the chartdata I think it has been passed to the Linechart.js, But why the chart does not update? Still empty
If you want the data to change on the fly, you either need the reactiveMixin http://vue-chartjs.org/#/home?id=reactive-data
Or you have to trigger an chart update by yourself.
This is because, even Vue.js is reactive, Chart.js per se is not.
If you want to update your chart, simply add a watcher to your LineChart.js component and watch for changes in chart. And then call .update()
import { Line } from 'vue-chartjs'
export default {
extends: Line,
props:['chart']
watch: {
chart () {
this.$data._chart.update()
}
}
mounted () {
this.renderChart({
labels: ['1','2','3','4','5','6','7'],
datasets: [
{
label: 'Data One',
backgroundColor: '#F64A32',
data: this.chart
}
]
}, {responsive: true, maintainAspectRatio: false})
}
}