vueJS table with dynamic data - api

I am trying to populate a table using bootStrap and vueJS using an API return from harry potter API. I can see the data is being returned but it does not show up on my DOM. I have a component called HouseRoster which I would like to deploy to create the tables for different houses.
<template>
<div>
<HouseRoster
house="Gryffindor"
fields="fields"
/>
</div>
</template>
<script>
import { mapState } from 'vuex'
import HouseRoster from '#/components/HouseRoster.vue'
export default {
components: {
HouseRoster
},
data () {
return {
fields: [
'name',
'role',
'bloodStatus',
'species'
],
characters: []
}
},
mounted: function () {
const house = 'Gryffindor'
const url = 'https://www.potterapi.com/v1/characters?key=key&house=' + house
fetch(url, {
method: 'get'
})
.then((response) => {
return response.json()
})
.then((jsonData) => {
this.characters = jsonData
})
},
computed: {
...mapState([
'Gryffindor'
])
}
}
</script>

Related

Problems with chart.js redrawing or not redrawing graphs

I am Japanese. Therefore, my sentences may be strange. Please keep that in mind.
I am writing code using vue.js, vuex, vue-chart.js and vue-chart.js to display the population of each prefecture of Japan when checked.I’m code is written to redraw the graph when the input element for each prefecture is checked.However, it does not redraw when checked.Also, it may redraw after half of the check.I believe this phenomenon can be confirmed from the following URL.
https://yumemi-coding.web.app/
※There are no errors.
Here's a question: what causes the graphs to redraw or not? Also, how can I code to remedy this?
What I have done to counteract the cause is as follows
I went to the official website and used the rendering process as a reference.
 URL:https://vue-chartjs.org/migration-guides/#new-reactivity-system
 => The way we did it was right.
We thought there was a problem with VueX and coded in a way that did not use it. => There was nothing wrong with vuex.
TopFroont.vue
<template>
<div class="Bar_area">
<Bar :options="chartOptions" :data="chartData" class="Bar_item" />
</div>
</template>
<script>
import { Bar } from "vue-chartjs"
import { Chart as ChartJS, registerables } from "chart.js"
ChartJS.register(...registerables)
export default {
name: "BarChart",
components: { Bar },
data() {
return {
chartOptions: {
responsive: true,
},
}
},
computed: {
chartData() {
return {
labels: this.$store.state.years,
datasets: this.$store.state.prefectures,
}
},
},
}
</script>
NaviBar.vue
<template>
<div class="navApp">
<ul>
<li v-for="(pref, index) in prefData" :key="index" class="pref_itemBox">
<label>
<input type="checkbox" #change="checkItem(pref)" />
<span class="pref_text">{{ pref.prefName }}</span>
</label>
</li>
</ul>
</div>
</template>
<script>
import resasInfo from "#/library/resas.js"
import axios from "axios"
export default {
data() {
return {
resasInfo: resasInfo,
url: resasInfo.url_prefectures,
api: resasInfo.api,
prefData: [],
prefectures: [],
}
},
async created() {
const request_Header = {
headers: { "X-API-KEY": this.api.key },
}
await axios.get(this.url, request_Header).then((res) => {
const value = res.data.result
this.prefData.push(...value)
})
},
methods: {
checkItem(pref) {
// チェックされてる都道府県のみを配列に入れる
const isExistencePref = this.prefectures.indexOf(pref)
isExistencePref === -1
? this.prefectures.push(pref)
: this.prefectures.splice(isExistencePref, 1)
this.$store.dispatch("getPrefectures", this.prefectures)
},
},
}
</script>
vuex => store/index.js
import axios from "axios"
import { createStore } from "vuex"
import createPersistedState from "vuex-persistedstate"
export default createStore({
state: {
prefectures: [],
years: [],
},
mutations: {
getPrefs(state, payload) {
state.prefectures = payload
},
getYears(state, payload) {
state.years = payload
},
},
actions: {
getPrefectures({ commit }, payload) {
// payload => 各都道府県のprefCode + prefName
const allPrefecture_Data = []
const result = payload.map(async (el) => {
const prefCode_data = el.prefCode
axios
.get(
`https://opendata.resas-portal.go.jp/api/v1/population/composition/perYear?prefCode=${prefCode_data}&cityCode=-`,
{
headers: {
"X-API-KEY": "5RDiLdZKag8c3NXpEMb1FcPQEIY3GVwgQwbLqFIx",
},
}
)
.then((res) => {
const value = res.data.result.data[0].data
const TotalPopulation_Year = []
const TotalPopulation_Data = []
// 都道府県の総人口データと年データを各配列に入れ込む
value.forEach((element) => {
TotalPopulation_Data.push(element.value)
TotalPopulation_Year.push(element.year)
})
// rgbaを自動生成する関数 => backgroundColor
const generateRGBA = () => {
const r = Math.floor(Math.random() * 256)
const g = Math.floor(Math.random() * 256)
const b = Math.floor(Math.random() * 256)
const a = 0.8
return `rgba(${r}, ${g}, ${b}, ${a})`
}
// chart.jsに入れ込むデータ
const prefData = {
label: el.prefName,
data: TotalPopulation_Data,
backgroundColor: generateRGBA(),
}
allPrefecture_Data.push(prefData)
commit("getPrefs", allPrefecture_Data)
commit("getYears", TotalPopulation_Year)
})
.catch((err) => {
console.log(err)
})
})
return result
},
},
plugins: [createPersistedState()],
getters: {},
modules: {},
})

How make json data available for my Vue dynamic routes

I have a List component where I fetch my date from db/blogs.json:
created() {
fetch('http://localhost:3000/blogs')
.then(response => {
return response.json();
})
.then(data => {
this.blogs = data;
})
},
In my BlogDetail.vue I have:
<script>
export default {
data: () => {
return {
blogId:this.$route.params.id
}
},
computed: {
blog() {
return this.blogs.find(
blog => blog.id === this.blogId
)
}
}
}
</script>
But how do I get the blogs data in this component, which I fetched in the List component?
Because now in the <template> section of my BlogDetail.vue I cannot access e.g. {{ blog.name }}
Update:
I try passing blogs with props:
Now I am accepting a prop in BlogDetails.vue:
props: {
blogs: {
type: Array
}
},
But from where (which component), I have to registering the prop like :blogs="blogs"?
Update 2:
This is what I have so far, link to the sandbox
Here is the working sandbox.
Firstly you need to import JSON data from your JSON file correctly. As:
<script>
import ListItem from "./ListItem";
import Blogs from "../../public/db/blogs.json";
export default {
name: "List",
components: {
ListItem
},
data() {
return {
blogs: Blogs.experiences
};
},
created() {}
};
</script>
Have to send props in the router-link as :
<router-link
:to="{ name: 'BlogDetails', params: { id: blog.id,blog:blog }}">More information
</router-link>
You can send props to the child component in the tag name, in your case:
//LIST component(PARENT)
<tamplate>
<BlogDetail :blogs="blogs"></BlogDetail> //CHILD component
</template>

Nuxt + Vuex mapGetters value is always undefined

I'm using VueX with Nuxt.JS so let's suppose the following code in the file store/search.js:
export const state = () => ({
results: null
});
export const mutations = {
setResults(state, { results }) {
state.results = results;
}
};
export const actions = {
startSearch({ commit, dispatch }, { type, filters }) {
commit("setResults", { type, filters });
}
};
export const getters = {
results: state => state.results
};
Now in my component results.vue, under the computed property I have something like this:
<template>
<button #click="handleSearch">Search</button>
<div v-if="results && results.length" class="results" >
<div v-for="item in results" :key="item.id">
{{item}}
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from "vuex";
data() {
return {
selected_type: null,
filters: null
};
},
methods: {
setType(type) {
this.selected_type = type;
this.handleSearch();
},
setFilters(filters) {
this.filters = filters;
},
handleSearch() {
this.startSearch({ type: this.selected_type, filters: this.filters });
},
...mapActions("search", {
startSearch: "startSearch"
})
},
computed: {
...mapGetters("search", {
results: "results"
})
}
</script>
My question is: why the item in the for loop (in the template section) always return undefined ?
Thank you very much for your answers.
So far, I found it:
in computed should be an array, not an object so:
...mapGetters("search", [
"results"
]
// Now results is populated.

chartJS pie chart not updating after axios GET

In my Vue app I'm loading a page and it grabs some data from my Flask backend. I draw a bunch of elements and I also draw a pie chart based on an array of 3 values returned from the backend. When I get the response I update this.pie_data and I thought this would update in my template to reflect the pie chart. It renders the elements that get set in this.nvrs so not sure why it doesn't work for my pie chart.
Appreciate the help.
Template
<div class="box">
<p class="title">System Overview</p>
<chart :type="'pie'": data=chartData></chart>
</div>
Script
import axios from 'axios'
import Chart from 'vue-bulma-chartjs'
export default {
name: 'NVR_Overview',
components: {
Chart,
},
data: () => ({
nvrs: [],
// Health, Down, Warn
pie_data: [],
}),
methods: {
goToNVR (nvrId)
{
let wpsId = this.$route.params['wpsId']
let path = '/wps/' + wpsId + '/nvr/' + nvrId
this.$router.push(path)
},
},
created ()
{
axios
.get('http://localhost:5000/wps/' + this.$route.params['wpsId'])
.then(response =>
{
this.nvrs = response.data['nvr_list']
this.pie_data = response.data['pie_data']
console.log(this.pie_data)
})
.catch(e =>
{
console.log(e)
})
},
computed: {
chartData ()
{
return {
labels: ['Healthy', 'Down', 'Warning'],
datasets: [
{
data: this.pie_data,
backgroundColor: ['#41B482', '#ff4853', '#FFCE56'],
},
],
}
},
},
}
Solution 1:
Copy old chart data reference when you make the change (old data have Observer, so don't make completed new object), instead of using computed value, use watch:
<template>
<div class="box">
<p class="title">System Overview</p>
<chart :type="'pie'" :data="chartData"></chart>
</div>
</template>
<script>
import axios from 'axios'
import Chart from 'vue-bulma-chartjs'
export default {
name: 'NVR_Overview',
components: {
Chart,
},
data: () => ({
nvrs: [],
// Health, Down, Warn
pie_data: [],
chartData: {
labels: ['Healthy', 'Down', 'Warning'],
datasets: [
{
data: [],
backgroundColor: ['#41B482', '#ff4853', '#FFCE56'],
},
]
}
}),
methods: {
goToNVR (nvrId)
{
let wpsId = this.$route.params['wpsId']
let path = '/wps/' + wpsId + '/nvr/' + nvrId
this.$router.push(path)
},
},
created ()
{
axios
.get('http://localhost:5000/wps/' + this.$route.params['wpsId'])
.then(response =>
{
this.nvrs = response.data['nvr_list']
this.pie_data = response.data['pie_data']
console.log(this.pie_data)
})
.catch(e =>
{
console.log(e)
})
},
watch: {
pie_data (newData) {
const data = this.chartData
data.datasets[0].data = newData
this.chartData = {...data}
}
},
}
</script>
You can check this problem on vue-bulma-chartjs repository https://github.com/vue-bulma/chartjs/pull/24
Solution 2:
Add ref to chart
<chart ref="chart" :type="'pie'" :data="data"</chart>
then in script after you assign data:
this.$nextTick(() => {
this.$refs.chart.resetChart();
})

Pre-fetch data using vuex and vue-resource

I'm building an app following this structure: http://vuex.vuejs.org/en/structure.html
My components/App.vue like this:
<template>
<div id="app">
<course :courses="courses"></course>
</div>
</template>
<script>
import Course from './course.vue'
import { addCourses } from '../vuex/actions'
export default {
vuex: {
getters: {
courses: state => state.courses,
},
actions: {
addCourses,
}
},
ready() {
this.addCourses(this.fetchCourses())
},
components: { Course },
methods: {
fetchCourses() {
// what do I have to do here
}
}
}
</script>
How can I fetch the data and set it to the state.courses ?
Thanks
I've just figured it out:
in /components/App.vue ready function, I just call:
ready() {
this.addCourses()
},
in vuex/actions.js:
import Vue from 'vue'
export const addCourses = ({ dispatch }) => {
Vue.http.get('/api/v1/courses')
.then(response => {
let courses = response.json()
courses.map(course => {
course.checked = false
return course
})
dispatch('ADD_COURSES', courses)
})
}
and in vuex/store.js:
const mutations = {
ADD_COURSES (state, courses) {
state.courses = courses
}
}