Vue js vuex unable to display my data in my loop - javascript

but i can't show the comments with v-for and i don't understand why my comment data is not working.
I know there is an error but I can't find it.
My request returns a data , but i can't display it my loop.
Thanks for your help
In store/index.js
state :{
dataComments:[]
}
mutation: {
getComments(state, dataComments) {
console.log(dataComments)
state.dataComments = dataComments;
},
}
action: {
getArticleComments: ({ commit }, dataArticles) => {
return new Promise(() => {
instance.get(`/comment/${dataArticles.article_id}`)
.then(function () {
commit('getComments');
})
.catch(function (error) {
console.log(error)
})
})
},
}
in my views/home.vue
export default {
name: "Home",
data: function () {
return {
articles: [],
comments: [],
}
},
methods: {
getArticleComments(comment) {
this.$store
.dispatch("getArticleComments",comment)
.then((res) => {
this.comments = res.data;
});
},
}
<div class="pos-add">
<button
#click="getArticleComments(article)"
type="button"
class="btn btn-link btn-sm">
Show comments
</button>
</div>
<!-- <div v-show="article.comments" class="container_comment"> -->
<div class="container_comment">
<ul class="list-group list-group comments">
<li
class="
list-group-item
fst-italic
list-group-item-action
comment
"
v-for="(comment, indexComment) in comments"
:key="indexComment"
>
{{ comment.comment_message }}
<!-- {{ comment.comment_message }} -->
</li>
</ul>
</div>

Your action getArticleComments does not return anything and I would avoid changing the action to return data. Instead remove the assignment to this.comments in home.vue
Actions do not return data, they get data, and call mutations that update your store.
Your store should have a getter that exposes the state, in this case the dataComments.
getters: {
dataComments (state) {
return state.dataComments;
}
}
Then in your home.vue you can use the helper mapGetters
computed: {
...mapGetters([
'dataComments'
])
}
You want your views to reference your getters in your store, then when any action updates them, they can be reactive.
More here: https://vuex.vuejs.org/guide/getters.html

As far as I see, you don't return any data in your getArticleComments action. To receive the comments you should return them, or even better, get them from your store data directly.
First make sure that you pass the response data to your mutation method:
getArticleComments: ({ commit }, dataArticles) => {
return new Promise(() => {
instance.get(`/comment/${dataArticles.article_id}`)
.then(function (res) {
commit('getComments', res.data);
})
.catch(function (error) {
console.log(error)
})
})
},
After dispatching you could either return the response data directly or you could access your store state directly. Best practice would be working with getters, which you should check in the vue docs.
getArticleComments(comment) {
this.$store
.dispatch("getArticleComments",comment)
.then((res) => {
// in your case there is no res, because you do not return anything
this.comments =
this.$store.state.dataComments;
});
},

Related

Cannot get data from v-for and the data is null

I'm stuck to get the data from the database through Axios using Vue.js. In Vue.js developer tools I can get the data from my database like this:
But when I loop using v-for like this:
<template>
<div class="flex flex-col items-center py-4">
<NewPost></NewPost>
<Post v-for="(post,i) in posts.data" :post="post" :key="i"/>
</div>
</template>
<script>
import NewPost from "../components/NewPost";
import Post from "../components/Post";
export default {
name: "Newsfeed",
components: {
NewPost,
Post
},
data: () => {
return {
posts: null
}
},
mounted() {
axios.get('/api/posts').then(res => {
this.posts = res.data
console.log(this.posts)
}).catch(error => {
console.log('Unable to fetch posts')
})
}
}
</script>
<style scoped>
</style>
The console says
"[Vue warn]: Error in render: "TypeError: Cannot read property 'data'
of null"
found in
---> at resources/js/views/Newsfeed.vue
at resources/js/components/App.vue
"
I don't understand because in Vue.js developers tools I can get the data. Is the looping wrong? Thank you!
Init that nested field with an empty array like :
data: () => {
return {
posts: {
data:[]
}
}
},
Another answer is to add the loading variable like this
In the data :
data: () => {
return {
posts: null,
loading: true
}
}
In the mounted()
mounted() {
axios.get('/api/posts').then(res => {
this.posts = res.data
this.loading = false
console.log(this.posts)
}).catch(error => {
this.loading = false
console.log('Unable to fetch posts')
})
}

Vue.js v-for in component renders when I visit the URL through a router-link but if I type the URL manually or refresh the page, v-for doesn't render

I have a pretty simple view that displays the icons of all characters from a certain game. If I were to visit the URL that displays that view through a router-link, everything works fine and I see the icons, however, if I then refresh the page, the icons disappear.
They also do not render at all if I manually type www.example.com/champions. Why is this happening.
My component:
<template>
<div class='wrapper'>
<div class="champions-container">
<div v-for='champion in champions' class="champion">
<img class='responsive-image' :src="'http://ddragon.leagueoflegends.com/cdn/' + $store.getters.version + '/img/champion/' + champion.image.full" alt="">
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return {
champions: this.$store.state.fullChampions
}
}
}
</script>
And my Vuex store where the champions are stored:
export default new Vuex.Store({
state: {
version: null,
fullChampions: null
},
mutations: {
version(state, data){
state.version = data.version
},
fullChampions(state, data){
state.fullChampions = data.fullChampions
}
},
actions: {
getVersion({commit}){
return axios.get("http://ddragon.leagueoflegends.com/api/versions.json")
.then((response) => {
commit('version', {
version: response.data[0]
})
})
.catch(function (error) {
console.log(error);
})
},
getFullChampions({commit, state}){
return axios.get("https://ddragon.leagueoflegends.com/cdn/" + state.version + "/data/en_US/championFull.json")
.then((response) => {
commit('fullChampions', {
fullChampions: Object.values(response.data.data)
})
})
.catch(function (error) {
console.log(error);
})
},
These might be because of these issues you encountered.
First: that component is not the one that dispatched your getFullChampions function in your vuex, might be in other component.
Second is that, you are already assigning the value of champions wherein the state fullChampions is not updated.
this.champions: this.$store.state.fullChampions // state.fullChampions might not yet updated.
Try this one might help you
watch: {
'$store.state.fullChampions': function() {
this.champions = this.$store.state.fullChampions
},
}
Last is to to do first a condition above your v-for to prevent the element
<div class="champions-container" v-if=""$store.getters.version>
<div v-for='champion in champions' class="champion">
<img class='responsive-image' :src="'http://ddragon.leagueoflegends.com/cdn/' + $store.getters.version + '/img/champion/' + champion.image.full" alt="">
</div>
</div>
Can you try to add this:
watch: {
$route: function(val, OldVal){
this.champions = this.$store.state.fullChampions;
}
},
after yuor data?
Upd.
If you are calling getFullChampions() action, then you can call it within watcher of my example instead of assigning to this.champions.

Errors: "[Vue warn]: Property or method "posts" is not defined on the instance but referenced during render." and also for "books"

enter image description hereI am making an app in Nuxt and vue using storyblok as my CMS. However, I have been receiving errors when trying to link the storyblok array to my arrays called in my template using v-for.
Here is the template:
<template>
<div>
<!-- instance header -->
<InstanceHeader title="Books" />
<div class="pageContainer">
<div class="booksInfoPost">
<div class="booksInfoPost__subHeader"><h3>Top Books</h3></div>
<div class="booksInfoPost__topBooks">
<BooksInfoPostTop
v-for="book in books"
:key ="book.id"
:bookCover="book.bookCover"
:title="book.title"
:author="book.author"
:content="book.content"
:id="book.id"
/>
</div>
<div class="booksInfoPost__subHeader"><h3>Book Titles</h3></div>
<BooksInfoPost
v-for="book in posts"
:key ="book.id"
:bookCover="book.bookCover"
:title="book.title"
:author="book.author"
:content="book.content"
:id="book.id"
/>
</div>
</div>
Here is my script:
export default {
components: {
InstanceHeader,
BooksInfoPostTop,
BookTitles,
BooksInfoPost
},
data() {
/* return {
books: [],
posts: []
} */
},
async asyncData(context) {
return {
bookTitles: context.app.$storyapi
.get("cdn/stories", { version: "draft", starts_with: 'books/book-titles'})
.then(response => {
console.log(response);
return {
posts: response.data.stories.map(bp => {
return {
id: bp.slug,
bookCover: bp.content.bookCover,
title: bp.content.title,
author: bp.content.author
};
}),
}
}),
topBooks: context.app.$storyapi
.get("cdn/stories", { version: "draft", starts_with: 'books/top-books'})
.then(response => {
console.log(response);
return {
books: response.data.stories.map(b => {
return {
id: b.slug,
bookCover: b.content.bookCover,
title: b.content.title,
author: b.content.author
};
}),
}
})
}
}
}
I noticed this error more when I tried calling two APIs from storyblok. When I called one API call I did not see this error. I have also tried using Axios but I am getting errors using that method as well. I am not the most experienced developer and If anyone can help I'll appreciate it. Thanks
export default {
components: {
InstanceHeader,
BooksInfoPostTop,
BookTitles,
BooksInfoPost
},
async asyncData(context) {
const result = {};
const mapBooks = b => {
return {
id: b.slug,
bookCover: b.content.bookCover,
title: b.content.title,
author: b.content.author
};
};
const { data } = await context.app.$storyapi
.get("cdn/stories", {
version: "draft",
starts_with: 'books/book-titles'
});
result.posts = data.stories.map(mapBooks);
const result = await context.app.$storyapi
.get("cdn/stories", {
version: "draft",
starts_with: 'books/top-books'
});
result.books = result.data.stories.map(mapBooks);
return result; // it has right property names {books:[], posts:[]}
}
}
Well as you mentioned in the comment it was a little mess before. So i tidied it up. The idea is that you need direct property names instead of nested objects. This way it should work, if it is not working check the network tab for the errors.

Vuejs set method return to template

I'm new to Vue and I'm stuck at the moment. For the practice I'm making an app for episode checklist for series. The first part of the app searches series and add one of them to a database. Result for the search gives me a result like this: https://i.stack.imgur.com/QuOfc.png
Heres my code with template and script:
<template>
<div class="series">
<ul>
<li v-for="item in series" :key="item.id">
<img :src="image_url+item.poster_path"/>
<div class="info">
{{item.name}}
<br/>
<h5>{{item.id}}</h5>
Start Date: {{item.first_air_date}}
<br/>
{{getEpisodeNumber(item.id)}}
<br/>
{{getSeasonNumber(item.id)}}
</div>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "series",
props: ["series"],
data() {
return {
image_url: "https://image.tmdb.org/t/p/w500",
api_key: {-api key-},
episode_url: "https://api.themoviedb.org/3/tv/",
}
},
methods: {
async getEpisodeNumber(showID) {
const json = await fetch(this.episode_url + showID + this.api_key)
.then((res) => { return res.json() })
.then((res) => { return res.number_of_episodes })
return await json
},
async getSeasonNumber(showID) {
const json = await fetch(this.episode_url + showID + this.api_key)
.then((res) => { return res.json() })
.then((res) => { return res.number_of_seasons })
return await json;
}
},
}
</script>
Methods should return to me a number but they return an object, probably promise object. But when I try to console.log the data in the methods they print a value(int). I need reach this value but I'm stuck. I tried to sort of thinks but it fails every time.
I just create a new component called show and pass item.id to this component. In show component, I use another fetch() to get show data again and now it works like I want.

Laravel delete method not working with vuejs

I am trying to complete a CRUD application with Vuejs and Laravel. Right now I can add an article but cannot delete and I ssee this error in my console:
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
The html inside the template is like the following:
<div class="card card-body"v-for="article in articles" :key="article.id">
<h3>{{ article.title }}</h3>
<p>{{ article.body }}</p>
<button #click="deleteArticle(article.id)" class="btn btn-danger">Delete</button>
</div>
Then inside the script I have this:
How can I make the delete work?
<script>
export default {
data(){
return{
articles: [],
article: {
id: '',
title: '',
body: ''
},
article_id: '',
pagination: {},
edit: false
}
},
created(){
this.fetchAllArticles();
},
methods: {
fetchAllArticles(){
fetch('/api/articles').then(res => res.json()).then(res => {
this.articles = res.data;
})
.catch(err => console.log(err));
},
deleteArticle(id){
if(confirm('Are you sure?')){
fetch('api/article/${id}', {
method: 'delete'
})
.then(res => res.json())
.then(data => {
alert('Article removed');
this.fetchAllArticles();
})
.catch(err => console.log(err));
}
}
}
}
</script>
If I type my url for the delete method I can view the data as you can see in the image:
My delete controller looks like this:
public function destroy($id)
{
// Get article
$article = Article::findOrFail($id);
if($article->delete()) {
return new ArticleResource($article);
}
}
From the netwok in the browser I see this:
Thanks in advance
I have never use fetch i love using axios, but through googling i found that you have to use not those symbols '' but those `` so:
fetch(`api/article/${id}`, {
method: 'delete'
})
From what I see in your console the API address is incorrect, should be 'api/article/' + id

Categories

Resources