Issue trying to output WordPress post data with Vue - javascript

Can anyone tell me why I am getting an error when trying to output the post data?
I've tried adding params like title, content but nothing works. I might add that I can get it to work using the id.
<template>
<section class="container animated fadeIn">
<nuxt-link :to="{ name: 'blog' }">
Back to Blog
</nuxt-link>
<div>
<h1 class="title">
{{ post }} <!-- this returns an array of the post data -->
{{ slug }} <!-- this returns the slug -->
{{ post.title }} <!-- this returns an error _vm.post is undefined -->
</h1>
</div>
</section>
</template>
<script>
import axios from 'axios'
export default {
name: 'post',
data () {
return {
slug: this.$route.params.slug,
post: {},
error: []
}
},
asyncData ({ params }) {
return axios.get(`http://localhost/amcdwp/wp-json/wp/v2/posts/?slug=${params.slug}`)
.then((response) => {
return { post: response.data }
})
}
}
</script>
I want to output individual data like post.title. I get an error of _vm.post is undefined

Related

Data from API doesn't show up in website but shows no error vuejs + axios

I'm learning vue js right now, and trying to get API data from this site https://reqres.in/ with axios. I want to take the data like email, name and put it into a card. It shows no error because the card is looping, but the data itself, like email and name, doesn't show up. How do I fix this?
here's is my script
data() {
return {
users: [],
};
},
methods: {
setUsers(data) {
this.users = data;
},
},
mounted() {
axios
.get("https://reqres.in/api/users")
.then((response) => this.setUsers(response.data))
.catch((error) => console.log("Gagal : ", error))
},
my card
<div class="row mb-3">
<div class="col md-2 mt-4" v-for="user in users" :key="user.id">
<card :user="user"/>
</div>
</div>
and my card components
<template>
<div>
<h2>Card API {{user.email}}</h2>
</div>
</template>
<script>
export default {
name: 'card',
props: ['user']
};
</script>
the output on my site is just 'Card API' looping for 6 times because the total data is 6 but not the email. Please help, thank you
The response.data you get is an object you fetched from the API. You need to access the "data" property of this object:
.then((response) => this.setUsers(response.data.data))

Access nested nodes with GraphQL (Nuxt)

i’m experiencing some issues with Apollo, GraphQL and Nuxt. i don’t know if it’s especially related to Nuxt though, or with vue.
i’m trying to use WordPress as headless CMS via WP-GraphQL plugin. here’s my query
WP-GraphQL interface
i basically created a graphql folder with a posts.js file inside, that contains my query
import gql from 'graphql-tag'
export const myQuery = gql`
query myQuery {
posts {
nodes {
id
title
date
slug
author {
node {
name
}
}
featuredImage {
node {
uri
sourceUrl
srcSet
}
}
}
}
}
`
then, all i need to do is to print my data in the template. here's the script part first.
<script>
import { myQuery } from '~/graphql/posts'
export default {
data() {
return {
posts: [],
}
},
apollo: {
posts: {
prefetch: true,
query: myQuery,
},
},
watch: {
async $route() {
await this.$nuxt.refresh()
window.scrollTo(0, 0)
},
},
transition: 'home',
async mounted() {
this.posts = await this.$apollo.query({ query: myQuery })
this.posts = this.posts.data.posts.nodes
this.loading = false
}
</script>
and then comes the template :
<template>
<section class="featured-projects">
<div class="featured-projects__wrapper">
<article v-for="post in posts" :key="post.id">
<p>{{ post.id }}</p>
<h2>{{ post.title }}</h2>
<span>{{ post.date }}</span>
</article>
</div>
</section>
</section>
</template>
everything just works!
now, i would like to print post author name as well. i first tried this :
<span>{{ post.author }}</span>
and this actually prints this :
{
"node": {
"name": "max max",
"__typename": "User"
},
"__typename": "NodeWithAuthorToUserConnectionEdge"
}
it totally makes sense, as author is an object with nested items in it. so according to what i’m being returned and following GraphQL API structure, to display post author name, think i should do something like this instead :
<span>{{ post.author.node.name }}</span>
and here’s the error i get, and i don’t know what to do to access what i want :
Cannot read property 'node' of undefined.
your problem arises from reading the data before it is loaded.
depending on your js settings you should be able to use one of the following:
<span>{{ post?.author.node.name }}</span>
or <span>{{ post ? post.author.node.name : '' }}</span>
according to the Vue Apollo documentation it could also be a problem with the duplication of the query
<script>
import { myQuery } from '~/graphql/posts'
export default {
data() {
return {
posts: [], // initialization
}
},
apollo: {
posts: {
prefetch: false, // to prevent SSR
query: myQuery,
update: data => {
console.log('overwrite posts with new data', data.posts)
return data.posts
}
},
}
}
</script>
further as there seem to be cases in which the author has more than one entry (perhaps co authors?) I would try to update the author rendering to the following:
<template>
<section class="featured-projects">
<div class="featured-projects__wrapper">
<article v-for="post in posts" :key="post.id">
<p>{{ post.id }}</p>
<div v-if="Array.isArray(post.author)">
first author is: {{ post.author[0].node.name }}
</div>
<div v-else-if="post.author">
author is: {{ post.author.node.name }}
</div>
<div v-else="post.author">
no author
</div>
</article>
</div>
</section>
</section>
</template>

Vue Bootstrap Pagination Define :Total-rows

I am learning to paginate data returned from an API using AXIOS. I have a working set of code, but there is a place in the code defined by bootstrap for :Total-rows, this is currently hardcoded but this creates extra rows based on the value rather than a computed value. I want to calculate the number of rows dynamically.
I know that I can count the response data from the api using: this.variable = response.data.length, but the way I am calling the data is using page variable to paginate.
Any suggestions on an efficient way to accomplish this somewhat seemingly simple call?
<template>
<div id="app">
<div class="row">
<div class="col-md-12">
<li v-for="item in todos" :key="item.id">
{{ item.name }} : {{ item.type }}
</li>
</div>
</div>
<b-pagination size="md" :total-rows="54" v-model="currentPage" :per-page="10" #input="getPostData(currentPage)">
</b-pagination>
</div>
</template>
VUE
<script>
//Import axios for REST API calls
import axios from 'axios'
import 'regenerator-runtime/runtime';
//Import bootstrap CSS
import 'bootstrap/dist/css/bootstrap.css'
//Import bootstrap vue CSS
import 'bootstrap-vue/dist/bootstrap-vue.css'
const baseURL = 'http://localhost:3000/todos?_page='+this.currentPage+'&_limit='+this.limit;
export default {
name: 'app',
data () {
return {
title: 'Vue.js Pagination Example With Bootstrap',
currentPage: 1,
limit: 5,
todos: [],
todoName: "",
todoType: "",
}
},
methods: {
// Fetches todos when the component is created.
getPostData (currentPage) {
axios.get('http://localhost:3000/todos?_page='+this.currentPage+'&_limit='+this.limit)
.then(response => {
//console.log(response)
// JSON responses are automatically parsed.
this.todos = response.data
})
.catch(e => {
this.errors.push(e)
})
},
async addTodo() {
const res = await axios.post(baseURL, {
name: this.todoName,
type: this.todoType,
});
this.todos = [...this.todos, res.data];
//resets the input field
this.todoName = "";
this.todoType = "";
},
}, //end of methods
//detects the current page on load
mounted(currentPage){
this.getPostData(currentPage)
}
}
</script>
You will need the API to return the total amount of rows, otherwise your frontend have no way of knowing how many pages to show.
You can find an example of this below, which use a dummy/testing API called reqres. This API returns various information, like the current page, total amount of rows and per page and of course the data for the requested page.
new Vue({
el: "#app",
data() {
return {
currentPage: 1,
totalRows: 0,
perPage: 0,
users: [],
request: null
}
},
methods: {
async getData(page) {
const response = await fetch(`https://reqres.in/api/users?page=${page}&per_page=3`).then(resp => resp.json())
this.perPage = response.per_page;
this.users = response.data;
this.totalRows = response.total;
// Only for testing purposes
this.request = response
}
},
created() {
this.getData(this.currentPage)
}
})
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/2.18.1/bootstrap-vue.min.css" />
<script src="//cdn.jsdelivr.net/npm/vue#2.6.12/dist/vue.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/2.18.1/bootstrap-vue.min.js"></script>
<div id="app">
<b-pagination
v-model="currentPage"
:total-rows="totalRows"
:per-page="perPage"
#change="getData">
</b-pagination>
<ul>
<li v-for="{ first_name, last_name } in users">
{{ first_name }} {{ last_name }}
</li>
</ul>
Request
<pre>{{ request }}</pre>
</div>

VueJs access data in array

I find myself facing a problem.
I need to retrieve a parameter in the url to display data dynamically but I can't find the solution.
what parameter must enter in state.event.aftermovies [] to have access to the id of my object.
If anyone has a solution, thanks
<template>
<div>
<div class="container text-center">
<div>
<h1>{{ aftermovie.id }}</h1>
<h1>{{ aftermovie.name }}</h1>
<h1>{{ aftermovie.slug }}</h1>
<h1>{{ aftermovie.video }}</h1>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
async fetch({ store, error, params }) {
try {
await store.dispatch('fetchEvent', params.id)
} catch (e) {
error({
statusCode: 503,
message: 'Unable to fetch event #' + params.id,
})
}
},
//Here is my problem
computed: mapState({
aftermovie: (state) => state.event.aftermovies[??????????????????]
}),
head() {
return {
title: this.aftermovie.name
}
}
}
</script>
and I would like to access the id of my object
event:Object
address:"Belgium"
aftermovies:Array[1]
0:Object
event_id:1
festival_id:""
id:4
name:"reverze 2020"
slug:"reverze-2020"
what is the right way ??
Assuming aftermovies is an array containing objects like:
aftermovies: [{
event_id:1,
festival_id:"",
id:4,
name:"reverze 2020",
slug:"reverze-2020"
}]
you could do something like aftermovies[0].id
Here is a jsfiddle example

How to loop through an API endpoint JSON Object in Vue & Axios?

I have an API endpoint which is a JSON object. I am using Axios and Vuejs to fetch the data into the DOM, but I am only able to get the whole object. When I tried to loop throught with the v-for directive it doesn't output the specific item in the object.
I fetched the data using Axios like so:
export default {
name: 'Reviews',
props: {
title: String
},
data(){
return {
info: []
}
},
// Life cycle hook that calls axios
mounted(){
axios.get('http://dev.muvtravel.com/index.php/explore/test?tripid=6590').then(response => {
console.log(response.data)
this.info = response.data
})
}
}
Then tried loop through using v-for
<div v-for="(item, index) in info" :key="index">
{{ item.establishment_address }}
{{ item.phone }}
</div>
<template>
<div class="reviews container-fluid">
<h1 class="text-center">{{ title }}</h1>
<b-container>
<b-row>
<b-col cols="12" sm="12" md="12" lg="4" xl="4">
Column 1
</b-col>
<b-col cols="12" sm="12" md="12" lg="8" xl="8">
Column 2
</b-col>
</b-row>
</b-container>
<div v-for="(item, index) in info" :key="index">
{{ item.establishment_address }}
{{ item.phone }}
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'Reviews',
props: {
title: String
},
data(){
return {
info: []
}
},
// Life cycle hook that calls axios
mounted(){
axios.get('http://dev.muvtravel.com/index.php/explore/test?tripid=6590').then(response => {
console.log(response.data)
this.info = response.data
})
}
}
</script>
<style scoped lang="scss">
</style>
Any help will be appreciate it
So I checked to see if the API endpoint in your code was publicly open - it is.
From looking at your payload, the reason your code isn't working is because you're trying to iterate on an object. The data object that you're returning is the FULL payload from that API endpoint, which is an object {"success": true, "data": [...]"}.
To more clearly illustrate what I'm talking about, here's an example fetch you can run:
fetch(yourAPIEndpoint).then(res => res.json()).then(data => console.log(data));
When I run that, it prints this to the console:
{success: true, data: Array(15)}
When I edit the console.log above to output data.data like so:
fetch(yourAPIEndpoint).then(res => res.json()).then(data => console.log(data.data));
I get the array of locations that you are trying to set.
TL;DR: You need to set this.info = response.data.data.
Happy coding!

Categories

Resources