Problem with uploading data from Vuex storage
Nikita
Posted on May 13, 2023
I have a ready-made implementation of displaying information about a Vue student in the form of a grid table. Also I need to display the same data only as a bar chart and pie chart. I decided to implement this using the library Chart.js . I have implemented the component StudentChar.vue and its display SecondView.vue. At the moment, StudentChart looks like this:
<template>
<v-container>
<v-row>
<v-col cols="6">
<v-card>
<v-card-title>Круговая диаграмма распределения оценок</v-card-title>
<v-card-text>
<canvas ref="pieChart" width="400" height="400"></canvas>
</v-card-text>
</v-card>
</v-col>
<v-col cols="6">
<v-card>
<v-card-title>Столбчатая диаграмма распределения оценок по курсам</v-card-title>
<v-card-text>
<canvas ref="barChart" width="400" height="400"></canvas>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script>
import Chart from 'chart.js';
export default {
name: 'StudentChart',
data() {
return {
pieData: [],
barData: [],
pieChart: null,
barChart: null,
};
},
async created() {
await this.loadData();
},
methods: {
async loadData() {
this.pieData = await this.$store.dispatch('grade/getGrades');
this.barData = await this.$store.dispatch('grade/getCourses');
this.createPieChart();
this.createBarChart();
},
createPieChart() {
const data = {
labels: this.pieData.map((grade) => grade.studentName),
datasets: [
{
data: this.pieData.map((grade) => grade.grade),
backgroundColor: [
'#FF6384',
'#36A2EB',
'#FFCE56',
'#8DFF00',
'#FF5733',
'#C41E3D',
],
hoverBackgroundColor: [
'#FF6384',
'#36A2EB',
'#FFCE56',
'#8DFF00',
'#FF5733',
'#C41E3D',
],
},
],
};
const options = {
responsive: true,
maintainAspectRatio: false,
legend: {
display: true,
position: 'right',
align: 'center',
labels: {
boxWidth: 20,
fontSize: 12,
},
},
tooltips: {
mode: 'index',
intersect: false,
},
};
this.pieChart = new Chart(this.$refs.pieChart, {
type: 'pie',
data,
options,
});
},
createBarChart() {
const data = {
labels: this.barData.map((course) => course.courseName),
datasets: [
{
label: 'Оценки',
backgroundColor: '#4CAF50',
data: this.barData.map((course) => course.averageGrade),
},
],
};
const options = {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
},
legend: {
display: false,
},
tooltips: {
mode: 'index',
intersect: false,
},
};
this.barChart = new Chart(this.$refs.barChart, {
type: 'bar',
data,
options,
});
},
},
};
</script>
But the data is not loaded from it, but for example in the first implementation they are loaded: GrdGrid.vue:
<template>
<v-data-table
:headers="headers"
:items="actualGrades"
:items-per-page="15"
item-key="code"
class="elevation-3"
>
<template v-slot:top>
<v-toolbar dense>
<v-toolbar-title>Таблица грейдов</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn class="primary text-lg-button"
@click="$store.state.grade.newGradeDialog = true"
x-small
fab
>
+</v-btn>
</v-toolbar>
</template>
<template v-slot:item.grade="editGrade">
<v-edit-dialog
:return-value.sync="editGrade.item.grade"
@save="save(editGrade)"
@open="open(editGrade.item.grade)"
>
{{ editGrade.item.grade }}
<template v-slot:input>
<v-text-field
v-model="editGrade.item.grade"
:rules="[rules.grade]"
label="Грейд"
></v-text-field>
</template>
</v-edit-dialog>
</template>
<template v-slot:item.actions="item">
<v-icon @click="deleteItem(item.item)">mdi-delete</v-icon>
</template>
<template v-slot:no-data v-if="!$store.state.isLoading">
<v-btn small color="primary" @click="initData">
Восстановить данные
</v-btn>
</template>
</v-data-table>
</template>
<script>
export default {
name: "GrdGrid",
data() {
return {
headers: [
{text: "Код", value: "code"},
{text: "Курс", value: "courseName"},
{text: "ФИО", value: "studentName"},
{text: "Грейд", value: "grade"},
{text: "Дата", value: "formatGradeDate", align: "center"},
{text: "Удалить", value: "actions", align: "center", sortable: false}
],
rules: {
grade: val => (val && !isNaN(val) && val >= 0 && val <= 25) || "число от 0 до 25"
},
currentGradeValue: null
};
},
methods: {
open(value) {
this.currentGradeValue = value;
},
async save(edit) {
let isError = 1;
if (this.rules.grade(edit.item.grade) === true) {
try {
edit.item.grade = Number(edit.item.grade);
isError = (await this.$store.dispatch("grade/putGrade", edit.item)).resultCode;
} catch (error) {
console.error(error);
}
}
setTimeout(() => (edit.item.grade = isError ? this.currentGradeValue : Number(edit.item.grade)));
},
deleteItem(grade) {
this.$store.dispatch("grade/deleteGrade", grade);
},
initData() {
this.$store.dispatch("grade/initData");
},
},
computed: {
actualGrades() {
return this.$store.state.grade.grades.filter(grade => !grade.isDelete);
}
},
async mounted() {
await this.$store.dispatch("grade/getCourses");
await this.$store.dispatch("student/getStudents");
await this.$store.dispatch("grade/getGrades");
}
};
</script>
what could be the problem? The file grade.js from the store looks like this:
import api from '@/store/api'
import Grade from '../../model/Grade'
import Course from '../../model/Course'
export default {
namespaced: true,
state: {
courses: new Map(),
grades: [],
newGradeDialog: false
},
mutations: {
setCourses(state, courses) {
state.courses.clear();
courses.forEach(course => {
state.courses.set(
course.code,
new Course(
course.code,
course.name,
course.dateStart,
course.dateEnd
)
);
});
},
setGrades(state, grades) {
state.grades = grades.map(grade => {
return new Grade(
grade.code,
grade.courseCode,
grade.studentCode,
grade.grade,
grade.gradeDate,
grade.isDelete
);
});
},
postGrade(state, grade) {
state.grades.push(
new Grade(
grade.code,
grade.courseCode,
grade.studentCode,
grade.grade,
grade.gradeDate,
grade.isDelete
)
);
},
deleteGrade(state, grade) {
const index = state.grades.indexOf(grade);
grade.isDelete = 1;
state.grades.splice(index, 1, grade);
}
},
actions: {
async getCourses(context) {
context.commit('setCourses', await api.course());
},
async getGrades(context) {
context.commit('setGrades', await api.grade());
},
async postGrade(context, grade) {
context.commit('postGrade', await api.postGrade(grade));
},
async putGrade(context, grade) {
return await api.putGrade(grade.code, grade);
},
async deleteGrade(context, grade) {
if(!(await api.deleteGrade(grade.code)).resultCode) {
context.commit('deleteGrade', grade);
}
},
async initData(context) {
context.commit('setGrades', await api.initData());
}
}
}
I've tried writing methods for loading data in different ways, but they all don't work. Also, for verification, I output the values of pie data and barbara in the methods to the console. They turned out to be undefined
Posted on May 13, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.