Initialization of variables with Vuex - vue.js

I made a VueJS 3 project with VueX to store the data.
When I print the variable data.doughnutChart.data in the following code it displays
{ "labels": [ "OK", "WARNING", "ERROR" ], "datasets": [ {
"backgroundColor": [ "#d4efdf", "#fdebd0", "#fadbd8" ], "data": [ 3,
1, 2 ] } ] }
But the graph doesn't use these data [3,1,2], the graph uses the values of the initialization in the index.js of VueX.
Here my code :
<template>
{{data.doughnutChart.data}}
<div style="height:200px;width: 200px; position:center">
<vue3-chart-js
:id="data.doughnutChart.id"
:type="data.doughnutChart.type"
:data="data.doughnutChart.data"
:options="data.doughnutChart.options"
></vue3-chart-js>
</div>
</template>
<script>
import Vue3ChartJs from '#j-t-mcc/vue3-chartjs'
export default {
name: 'App',
components: {
Vue3ChartJs,
},
beforeMount() {
this.$store.dispatch("getData");
},
computed: {
data() {
return {
doughnutChart: {
id: 'doughnut',
type: 'doughnut',
data: {
labels: ['OK', 'WARNING', 'ERROR'],
datasets: [
{
backgroundColor: [
'#d4efdf',
'#fdebd0',
'#fadbd8'
],
data: [this.$store.state.nbOk, this.$store.state.nbWarning, this.$store.state.nbError]
}
]
},
options:
{
plugins: {
legend: {
display: false
},
title: {
display: true,
text: 'Current situation'
}
},
}
}
}
}
}
}
</script>
I read the value in my index.js (VueX) :
import axios from 'axios'
import { createStore } from 'vuex'
export default createStore({
state: {
data: [],
nbError : 0,
nbWarning : 0,
},
actions: {
getData({commit}){
axios.get('http://localhost:8080/data/mock.json')
.then(res => {
commit('SET_DATA', res.data)
})}
},
mutations: {
SET_DATA(state, data){
state.data = data.data;
state.nbWarning = 0;
state.nbError = 0;
for (let i = 0; i < state.data.length; i++) {
if(state.data[i].status == 'WARNING'){
state.nbWarning += 1;
};
if(state.data[i].status == 'ERROR'){
state.nbError += 1;
};
};
}
})
However it works when, in my Vuejs project, I go in an other page and come back but not when I just open the project or refresh the page.
Do you know why ?

data property should be defined as computed in order to receive store changes:
<template>
{{data}}
</template>
<script>
export default {
data() {
return {
}
},
computed:{
data(){
return [this.$store.state.nbWarning, this.$store.state.nbError]
}
},
beforeMount() {
this.$store.dispatch("getData");
}
}
</script>

Related

v-if is not updated when importing a 3rd party script with vue-meta

I want to use vue-meta to import a 3rd party SwiperJS script into my nuxt website.
The script is loaded only after mounted()-hook is called so I also initialize it on update(). This kind of works but the v-if on the wrapper does not update.
<template>
<section
class="swiper"
v-if="isSwiperLoaded"
>
<div class="swiper-wrapper"> ... </div>
</section>
</template>
<script>
export default {
data() {
return { swiperLoaded: false, swiperInitialized: false }
},
computed: {
isSwiperLoaded: {
get() {
return this.swiperLoaded
},
set(value) {
this.swiperLoaded = value
},
},
isSwiperInitialized: {
get() {
return this.swiperInitialized
},
set(value) {
this.swiperInitialized = value
},
},
},
head() {
return {
script: [
{
hid: 'swiper',
src: 'https://cdn.jsdelivr.net/npm/swiper#8/swiper-bundle.min.js',
defer: true,
// Changed after script load
callback: () => {
this.isSwiperLoaded = true
},
},
],
link: [
{
rel: 'stylesheet',
type: 'text/css',
href: 'https://cdn.jsdelivr.net/npm/swiper#8/swiper-bundle.min.css',
},
],
}
},
methods: {
initSwiper() {
const swiperOptions = {
...
}
let swiper = new Swiper(this.$el, swiperOptions)
},
},
mounted() {
if (!this.isSwiperInitialized && this.isSwiperLoaded) {
console.log('INIT LOADED')
this.initSwiper()
this.isSwiperInitialized = true
}
},
updated() {
if (!this.isSwiperInitialized && this.isSwiperLoaded) {
console.log('UPD LOADED')
this.initSwiper()
this.isSwiperInitialized = true
}
},
}
</script>
Also I noticed the computed values are normally for getting and setting values from store and not local values. Maybe there is an easier way of updating the variables.

How to use v-model in QuillJS in vue 3 app?

If I try to use v-model in the div with editor reference it gives me this error:
"'v-model' directives aren't supported on elements."
<div ref="editor"></div>
<script>
import Quill from "quill";
export default {
data() {
return {
description: "", // variable that I'm trying to use in v-model
options: {
modules: {
toolbar: ["bold", "italic", { list: "ordered" }, { list: "bullet" }],
},
theme: "snow",
},
};
},
watch: {
isDescription(newVal, oldVal) {
if (newVal == true) {
setTimeout(() => {
new Quill(this.$refs.editor, this.options);
}, 1);
}
},
},
};
</script>

Unable to display chart using API call in chartjs in the context of Vuejs

Im trying to display chart using chartjs by calling API, but unable to do so.
Here s my LineChart.vue:
<script>
import {Line, mixins} from 'vue-chartjs' // We specify what type of chart we want from vue-chartjs and the mixins module
const { reactiveProp } = mixins
export default { //We are extending the base chart class as mentioned above
extends: Line,
mixins: [reactiveProp],
data () {
return {
options: { //chart options
lineTension: 0,
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
yAxes: [
{
scaleLabel: {
display: false
},
ticks: {
beginAtZero: true,
// eslint-disable-next-line no-unused-vars
callback (value, index, values) {
return `${value }%`
}
}
}
],
xAxes: [
{
type: 'time',
time: {
unit: 'month'
},
scaleLabel: {
display: true,
labelString: ''
}
}
]
}
}
}
},
mounted () {
// this.chartData is created in the mixin
this.renderChart(this.chartData, this.options)
}
}
</script>
And here is my Home.vue where i have imported the LineChart:
<template>
<div class="chart">
<line-chart :chart-data="datacollection"></line-chart>
</div>
</template>
<script>
import LineChart from './LineChart'
import axios from 'axios'
import DateTime from 'luxon'
export default {
data () {
return {
date: {},
challenge: {},
datacollection: {}
}
},
component: {LineChart},
created() {
this.fillData()
},
mounted () {
this.fillData()
},
methods: {
fillData () {
axios.get('https://my_api_goes_here')
.then(response => {
const results = response.data
const dateresult = results.map(a => a.date)
const challengeresult = results.map(a => a.challenge)
this.date = dateresult
this.challenge = challengeresult
this.datacollection = {
labels: [this.date].map(labels => DateTime.fromMillis(labels * 1000).toFormat('MMM yyyy')),
datasets: [
{
data: [this.challenge],
label: 'Africa',
borderColor: '#7367F0'
}
]
}
})
.catch(error => {
console.log(error)
})
}
}
}
</script>
Dont know why the chart did not appear even though my other resources have been loaded from the API call, when i checked out my console, this is what error im getting:
TypeError: results.map is not a function
Please check out my logic and let me where the error is.

Can't render chart, data from api

I get data from api. i can show chartdata but it not render a chart.
my code:
<script>
import { Pie, mixins } from 'vue-chartjs'
import axios from 'axios'
export default {
mixins: [mixins.reactiveData],
extends: Pie,
data() {
return {
chartdata: ''
}
},
mounted () {
this.renderChart(this.chartdata, this.options)
},
created() {
axios.get("http://localhost:3000/chart1")
.then(response => {
const responseData = response.data
this.chartdata = {
labels: responseData.map(item => item.lb),
datasets:
[
{
label: 'hrlo',
backgroundColor: ['purple','#b2b2b2'],
data: responseData.map(item => item.dt)
}
]
}
})
.catch( e => {
this.errors.push(e)
})
},
}
</script>
api: [
{
"lb": "Android",
"dt": 80
},
{
"lb": "IOS",
"dt": 20
}
]
i'm sorry because of my bad english.
Can you also include any error messages? I am suspecting that the wrong data structure of "chartdata" is causing an error before even retrieving the data to display, i.e. "chartdata" needs to be
chartdata: {
labels: [],
datasets: []
}

Emit filtered rows count in ag grid vue

I am trying to emit filtered rows count from ag grid table which is my child component to the parent component
<template>
<ag-grid-vue
style="width: 100%; height: 600px"
class="ag-theme-balham"
id="myGrid"
:enableRangeSelection="true"
:defaultColDef="{
resizable: true,
sortable: true,
filter: true,
width: 100
}"
:columnDefs="columnDefs"
:gridOptions="gridOptions"
:processCellForClipboard="processCellForClipboard"
:rowData="newRowData"
:modules="[...agModule, ...agCModule]"
></ag-grid-vue>
</template>
<script>
import { AgGridVue } from "ag-grid-vue";
import "ag-grid-enterprise";
import { LicenseManager } from "ag-grid-enterprise";
import { AllModules } from "ag-grid-enterprise/dist/ag-grid-enterprise";
import { AllCommunityModules } from "ag-grid-community/dist/ag-grid-community";
LicenseManager.setLicenseKey(process.env.VUE_APP_AG_KEY);
import axios from "axios";
export default {
name: "Table",
props: {
columnDefs: {
type: Array,
default() {
return null;
}
},
rowData: {
type: Array,
default() {
return null;
}
}
},
components: {
"ag-grid-vue": AgGridVue
},
data() {
return {
agModule: AllModules,
agCModule: AllCommunityModules,
newRowData: [],
gridApi: null,
gridOptions: {}
};
},
watch: {
rowData: function(newVal, oldVal) {
this.newRowData = newVal;
},
count: "getDisplayedRowCount"
},
computed: {
count() {
return this.gridApi.getDisplayedRowCount();
}
},
beforeMount() {
this.processCellForClipboard = params => {
return `${params.value.trim()},`;
};
},
methods: {
getDisplayedRowCount() {
console.log("getDisplayedRowCount() => " + this.count);
this.$emit("filteredrows", this.count);
}
},
mounted() {
this.newRowData = this.rowData;
this.gridApi = this.gridOptions.api;
}
};
</script>
<style lang="sass" scoped>
#import "../../../node_modules/ag-grid-community/dist/styles/ag-grid.css"
#import "../../../node_modules/ag-grid-community/dist/styles/ag-theme-balham.css"
</style>
This is how my child component looks.
But when the ag grid table loads the gridapi value is null, due to which i do not get the value of count defined in computed property. I want to call the function getDisplayedRowCount each time there is change in no of rows. How can I achieve this?
You can write your computed property like this
computed: {
count() {
if (this.gridApi) {
return this.gridApi.getDisplayedRowCount();
} else {
return this.newRowData.length;
}
}
},