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
Top comments (0)