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

[Bug]: Read only issue while using vue-query #1039

Closed
1 task done
shankhadevpadam opened this issue May 26, 2023 · 3 comments
Closed
1 task done

[Bug]: Read only issue while using vue-query #1039

shankhadevpadam opened this issue May 26, 2023 · 3 comments

Comments

@shankhadevpadam
Copy link

Would you like to work on a fix?

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

Current and expected behavior

<script setup>
import { ref } from 'vue'
import { useQuery } from '@tanstack/vue-query'
import { Line } from 'vue-chartjs'
import Api from '../Api/api'
import DatePicker from 'vue-datepicker-next'
import 'vue-datepicker-next/index.css'

import {
    Chart as ChartJS,
    CategoryScale,
    LinearScale,
    PointElement,
    LineElement,
    Title,
    Tooltip,
    Legend,
} from 'chart.js'

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

const props = defineProps({
    userId: {
        type: Number,
        required: true,
    },
})

const filter = ref('last-7-days')

const dateRange = ref(null)

const chartQuery = useQuery({
    queryKey: ['chart-data', filter],
    queryFn: async () => {
        const response = await Api.get(
            `/affiliate/stats/user/${props.userId}?filter=${filter.value}`
        )

        return response.data
    },
})

const setFilter = (param) => {
    filter.value = param
}

const onConfirm = (date) => {
    //console.log(date);
}
</script>

<template>
    <div class="row">
        <div class="col-md-8 col-sm-12">
            <div class="card">
                <div class="card-header border-0">
                    <div class="d-flex justify-content-between">
                        <h3 class="card-title">Total Revenue</h3>
                    </div>

                    <div class="d-flex justify-content-between">
                        <strong
                            class="total-revenue"
                            v-text="chartQuery.isLoading.value ? 0 : chartQuery.data.value.total"
                        ></strong>

                        <div class="filter">
                            <div class="dropdown d-inline mr-2">
                                <button
                                    class="btn btn-secondary dropdown-toggle"
                                    type="button"
                                    data-toggle="dropdown"
                                    aria-expanded="false"
                                >
                                    {{
                                        filter
                                            .split('-')
                                            .join(' ')
                                            .toUpperCase()
                                    }}
                                </button>
                                <div class="dropdown-menu">
                                    <a
                                        class="dropdown-item"
                                        href="javascript:;"
                                        @click="setFilter('last-7-days')"
                                        >Last 7 Days</a
                                    >
                                    <a
                                        class="dropdown-item"
                                        href="javascript:;"
                                        @click="setFilter('last-month')"
                                        >Last Month</a
                                    >
                                    <a
                                        class="dropdown-item"
                                        href="javascript:;"
                                        @click="setFilter('this-year')"
                                        >This Year</a
                                    >
                                </div>
                            </div>
                            <date-picker
                                v-model:value="dateRange"
                                @confirm="onConfirm"
                                value-type="format"
                                format="YYYY-MM-DD"
                                :confirm="true"
                                range
                                placeholder="Select date range"
                            ></date-picker>
                        </div>
                    </div>
                </div>
                <div class="card-body">
                    <span v-if="chartQuery.isLoading.value">Loading...</span>
                    <span v-else-if="chartQuery.isError.value">Error: {{ chartQuery.error.value }}</span>
                    <Line v-else :data="chartQuery.data.value.chart_data" />
                </div>
            </div>
        </div>

        <div class="col-md-4 col-sm-12">
            <div class="card">
                <div class="card-header border-0">
                    <div class="d-flex justify-content-between">
                        <h3 class="card-title">Refunds</h3>
                    </div>

                    <div class="d-flex justify-content-between">
                        <strong class="total-revenue">$15342</strong>
                    </div>
                </div>
                <div class="card-body"></div>
            </div>
        </div>
    </div>
</template>

<style>
.total-revenue {
    font-size: 25px;
}

.mx-input {
    height: 37px !important;
}
</style>

Faced Issue

[Vue warn] Delete operation on key "0" failed: target is readonly. Proxy(Array) {0: LineController}
[Vue warn] Set operation on key "length" failed: target is readonly.

While change the filter dropdown first time i faced this issue.

Reproduction

https://stackblitz.com/github/apertureless/vue-chartjs/tree/main/sandboxes/bar?file=index.ts

chart.js version

4.3.0

vue-chartjs version

5.2.0

Possible solution

No response

@apertureless
Copy link
Owner

Well I guess this is because if you change the filter, you modify the whole data object. You should try to make a copy and then after replacing it, manually updating the chart with update()

@wjlee2020
Copy link
Contributor

wjlee2020 commented Feb 1, 2024

I'm not sure why this is closed. The documentation says:

Since v4 charts have data change watcher and options change watcher by default. Wrapper will update or re-render the chart if new data or new options is passed
computed: {
      chartData() { return /* mutable chart data */ },
      chartOptions() { return /* mutable chart options */ }
    }

It says mutable chart data, and so I feel like I should be able to just mutate it.
However, using computed without creating a setter, vue will throw the warning about read-only, correct?
Vue Chartjs documentation also doesn't mention updating the chart manually with vanilla chart js update() method.

Sorry to be nit-picky, but this is an annoying warning that shouldn't be there or updating charts should be documented clearly.

I was able to work around it by doing this:

<Line
  id="my-chart-id"
  :options="lineOptions"
  :data="JSON.parse(JSON.stringify(chartData))"
/>

@apertureless
Copy link
Owner

Feel free to make a fix pr :)

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

3 participants