Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mixed chart types support #1048

Open
1 task
ActuallyHappening opened this issue Jul 7, 2023 · 5 comments
Open
1 task

Mixed chart types support #1048

ActuallyHappening opened this issue Jul 7, 2023 · 5 comments

Comments

@ActuallyHappening
Copy link

ActuallyHappening commented Jul 7, 2023

Would you like to work on this feature?

  • Check this if you would like to implement a PR, we are more than happy to help you go through the process.

What problem are you trying to solve?

I have a type issue when I try to mix chart types

Describe the solution you'd like

I would like a specific , preferably typed way, of mixing chart types.
As shown in official documentation of ChartJS: https://www.chartjs.org/docs/latest/charts/mixed.html

Describe alternatives you've considered

Access the underlying chart JS instance and manually add my own data

Documentation, Adoption, Migration Strategy

<Bar :data="{
        datasets: [{
            type: 'bar',
            label: 'Bar Dataset',
            data: [10, 20, 30, 40]
        }, {
            type: 'line',
            label: 'Line Dataset',
            data: [50, 50, 50, 50],
        }],
        labels: ['January', 'February', 'March', 'April']
    }" />
@palomamtnez
Copy link

Bumping this.
Is there any work arounds to do mixed chart types at the moment?

@palomamtnez
Copy link

Hm, after looking for some other answers on Stackoverflow, I was able to generate a bar chart with line charts on top of it.

Example of my component:

<script setup>
import {Chart as ChartJS, Title, LineElement, PointElement, Tooltip, Legend, BarElement, CategoryScale,Filler, LinearScale} from 'chart.js'
import {Bar} from 'vue-chartjs'
import {computed, defineProps} from 'vue'

ChartJS.register(CategoryScale, PointElement, LineElement, LinearScale, BarElement, Title, Tooltip, Filler,  Legend)

const props = defineProps({
    labels: Array,
    dataRange: Array,
    dataTrend: Array,
    dataAvg: Array,
})

const chartData = computed(() => {
    return {
        labels: props.labels,
        datasets: [
            {
                type: 'line',
                label: "Average ($)",
                borderColor: "#004BA8",
                backgroundColor: "#004BA8",
                borderWidth: 2,
                data: props.dataAvg,
                tension: 0.1,
            },
            {
                type: 'line',
                label: "Trend ($)",
                backgroundColor: "#E57A44",
                borderColor: "#E57A44",
                borderWidth: 2,
                data: props.dataTrend,
                tension: 0.1,
            },
            {
                type: 'bar',
                label: "Min - Max ($)",
                data: props.dataRange,
                backgroundColor: '#188145a8',
                radius:  props.labels.length > 30 ? 0 : 3,
            },
        ]
    }
})

const chartOptions = computed(() => {
    return {
        tooltips: {
            mode: 'index',
            intersect: true,
            displayColors: false,
        },
        interaction: {
            mode: 'index'
        },
        responsive: true,
        title: {
            display: true,
            text: "Sale Price ($)"
        },
        scales: {
            x: {
                stacked: true,
                time: {
                    // Luxon format string
                    tooltipFormat: 'DD T'
                },
                format: "HH mm",
                title: {
                    display: true,
                    text: 'Date'
                }
            },
            y: {
                stacked: false,
                title: {
                    display: true,
                    text: 'Cents per kg'
                },
                suggestedMin: 0,
                suggestedMax: props.dataAvg.length > 0 ? Math.max(...props.dataAvg)+10 : 0
            }
        },
    }
})
</script>

<template>
    <Bar v-if="dataRange?.length" :data="chartData" :options="chartOptions"/>
</template>

Generates this (what I needed):
Screen Shot 2023-08-27 at 11 57 28 AM

Im using:
"vue-chartjs": "^5.2.0",
"chart.js": "^4.4.0",
"vue": "^3.2.31",

@mewforest
Copy link

Hm, after looking for some other answers on Stackoverflow, I was able to generate a bar chart with line charts on top of it

Such a brilliant answer! This example have to be included in documentation 🙏🏻

@raam86
Copy link

raam86 commented Oct 2, 2023

In case someone is stuck with typescript error:
like Type '{ labels: string[]; datasets: ({ data: number[]; label: string; backgroundColor: string; } | { label: string; data: number[]; type: string; pointStyle: string; pointRadius: number; borderColor: string; })[]; }' is not assignable to type 'ChartData<"bar", (number | [number, number] | null)[], unknown>'. for type mismatch

you need to uncomment the "other" type declaration so if you are using only leave the "line" type for combining bar and line charts

let bar_dataset_obj = {
    data: data,
    label: 'Label',
    // type: 'bar', //for mixed charts only the "other" type should be declared
    // backgroundColor: '#85bb65' //for some reason other attributes do not work any longer on this object
  }

  let line_dataset_obj = {
    label: 'Label',
    data: data,
    type: 'line' // this is the other 'type'
  }

@wcheek
Copy link

wcheek commented Apr 24, 2024

Thanks to the people above for figuring this out! However, type support is still needed and @raam86 's suggestion didn't work for me.

Here is my implementation where I have to use any to get past the type fences.

Note: This also happens to be an example of using multiple axes

<template>
  <Bar :data="chartData" :options="options" />
</template>

<script setup lang="ts">
import { computed, ref } from "vue";
import { Bar } from "vue-chartjs";

const options = ref<any>({
  scales: {
    ybar: {
      type: "linear",
      position: "left",
    },
    yline: {
      type: "linear",
      position: "right",
    },
  },
});

const datasets = computed(() => {
  let toPlot= [];

  // This is the bar graph
  toPlot.push({
    label: <bar label>,
    data: <bar data>,
    yAxisID: "ybar",
  });
  // This is the line graph
  toPlot.push({
    type: "line",
    label: <line label>,
    data: <line data>,
    yAxisID: "yline",
  });

  return toPlot;
});

// HERE I need to use `any` to be able to pass into the Bar :data prop
const chartData = computed<any>(() => {
  return { labels: <my labels>, datasets: datasets.value };
});
</script>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants
@raam86 @palomamtnez @mewforest @wcheek @ActuallyHappening and others