VueJS 3 Composition API. Can anyone explain why this will not work? - vuejs3

I'm loading a simple JSON file, assigning it to a reactive variable, and displaying it in the template. However, it only works partly.
{{ people }}, {{ people.People }}, and in a people.People in a v-for loop work as expected,
but accessing the people.People[0].FullName fails. But why? Any insight is appreciated.
Here is my .json
{
"People": [
{
"FullName": "The Json"
}, {
"FullName": "The Jetsons"
}
]
}
And here is the component.vue code
<template>
<h1>Test</h1>
<div>
<p>{{ people }}</p> <!-- Works and displays: { "People": [ { "FullName": "The Json" }, { "FullName": "The Jetsons" } ] } -->
<p>{{ people.People }}</p> <!-- Works and displays: [ { "FullName": "The Json" }, { "FullName": "The Jetsons" } ] -->
<p>{{ people.People[0].FullName }}</p> FAILS - Uncaught TypeError: $setup.people.People is undefined
<p v-for="(item, idx) in people.People" :key="idx">
{{ item.FullName }} <!-- Works as expected -->
</p>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
name: "Test",
setup() {
const people = ref({});
fetch('http://localhost:3000/data/people.json')
.then(response => response.json())
.then(data => people.value = data);
return {
people
}
}
}
</script>
<style>
</style>```
Thanks

At "setup time" before your json is loaded :
people = {}, so people.People[Ø] raises an error cause people.People is not defined at this moment
In your exemple
{{ people }} and {{ people.People }} display something cause it's reactive and you just don't have time to see it before the json is loaded
There is several ways to manage this. ere is two of them
Add an if
<p v-if="people.People">{{ people.People[0].FullName }}</p>
Init with default walues
const people = ref({
People: []
});

Related

Why my async fetch doesn't work client side?

I'm having an issue to get my component working client side with fetch (it's ok when I'm refreshing the page) in Nuxt.
The $fetchState.error doesn't load any error though. But my console.log in my mounted hook doesn't load any data.
I don't know what I'm doing wrong here. I'm using target: 'static'
<template>
<p v-if="$fetchState.pending">Fetching realisation...</p>
<p v-else-if="$fetchState.error">An error occurred :(</p>
<nuxt-link v-else :to="real.full_slug" class="real">
<div class="real__content">
<h2>{{ real.name }}</h2>
</div>
</nuxt-link>
</template>
<script>
export default {
props: {
realisation: {
type: Object,
required: true
}
},
data() {
return {
real: {}
}
},
async fetch() {
this.real = await this.$storyapi
.get(`cdn/stories/${this.realisation.work}`, {
version: 'published',
find_by: 'uuid'
})
.then((res) => {
return res.data.story
})
.catch((err) => console.log(err))
},
mounted() {
console.log(this.real)
},
fetchOnServer: true
}
</script>

Vuelidate vue.js latest for vue3 using the helpers.forEach approach for array of objects

Using Vuelidate vue.js latest for vue3 using the helpers.forEach approach for array of objects. I tried running the form but the validation is causing an error given as the below
Gives $response.$errors is undefined in the console
Uncaught (in promise) TypeError: $response.$errors is undefined
export default {
setup () {
const rules = {
collection: {
$each: helpers.forEach({
name: {
required
}
})
}
}
const state = reactive({
collection: [
{ name: '' },
]
})
const v = useVuelidate(rules, state)
return { v, state }
}
}
This is the template of the code
<div
v-for="(input, index) in state.collection"
:key="index"
:class="{
error: v$.collection.$each.$response.$errors[index].name.length,
}"
>
<input v-model="input.name" type="text" />
<div
v-for="error in v$.collection.$each.$response.$errors[index].name"
:key="error"
>
{{ error.$message }}
</div>
</div>
</template>
Little late, but in your template you are refering to v$.collection instead of v.collection. In your setup you are returning v and not v$
I need to use v$ as this was v$ represented a global variable based on useVuelidate

How should I be referencing firebase data in Vue component?

I can see the data in the Vue console but I'm getting an error in the console: 'Property or method "rsvp" is not defined on the instance but referenced during render.'
How should I be referencing the firebase data?
<template>
<ul>
<li
v-for="(data, index) in rsvp"
:key="index"
>
<div
v-for="(name, index) in data.name"
:key="index"
>
{{ name }}
</div>
<div v-if="data.dietRestrictions">
Diet Restrictions: {{ data.dietRestrictions }}
</div>
</li>
</ul>
</template>
<script>
import { db } from "../../config/db";
export default {
name: "Results",
firebase: {
rsvp: db.ref("rsvp"),
},
}
</script>
I just forgot to declare rsvp in data().
data() {
return {
rsvp: {},
}
},

VUEJS + Firestore how to output Data?

I created a post and stored it in Cloud Firestore and now I would like to output the data in my vueJs file called Dashboard.vue.
But I do not know how it works. I tried some ideas by myself without a good end result.
So how can I output this data?
Files:
Firebase => Cloud Firestore
created post data in firebase:
and
create post method in vueJs post.vue
createPost () {
fb.postsCollection.add({
postDetails: {
createdOn: this.postDetails.createdOn,
content: this.postDetails.content,
userId: this.currentUser.uid,
image: this.postDetails.image,
comments: this.postDetails.comments,
likes: this.postDetails.likes
}
}).then(ref => {
this.post.content = ''
this.$router.push('/dashboard')
}).catch(err => {
console.log(err)
})
}
Do as follows:
Create a posts array in your data:
...
data() {
return {
posts: []
}
},
....
Then create a method that fetches the records and assigns the result to the posts array:
methods:{
getPosts: function() {
fb.postsCollection.orderBy('createdOn', 'desc').onSnapshot(querySnapshot => {
let postsArray = []
querySnapshot.forEach(doc => {
let post = doc.data()
post.id = doc.id
postsArray.push(post)
})
this.posts = postsArray;
})
}
},
.....
Call the method in the beforeMount() lifecycle hook:
beforeMount(){
this.getPosts()
},
Then render the posts out to the DOM. For example:
<div v-if="posts.length">
<div v-for="post in posts">
<h4>{{ post.createdOn }}</h4>
<p>{{ post.content}}</p>
<ul>
<li>comments {{ post.comments }}</li>
</ul>
</div>
</div>
<div v-else>
<p>There are currently no posts</p>
</div>

Vue.js and Firebase - return query based on route param

I'm working on something in Vue.js where I need to pass a value (symbol) that is coming from vue-router into a Firebase database query to retrieve the JSON object that matches that query. I can only do this via a v-for / v-if hack within the template. I know there must be a way to simply return this query within my script tags.
I have access to the database via the vuefire plugin.
<template>
<div>
<h3>Edit Crypto</h3>
<div v-for="crypto in getCryptos" :key="crypto[symbol]">
<div v-if="crypto.symbol === symbol">
{{ crypto.name }} - {{ crypto.symbol }}
</div>
</div>
<div>
{{ cryptoTest }}
</div>
</div>
</template>
dbCryptosRef is the database (image below) reference. getCrypto is the method I am trying to use to query the dabase. Below is the script tag within the same file. dbCryptosRef.equalTo(this.$route.params.symbol) simply returns the url for the firebase database, not as JSON object. What am I doing wrong?
<script>
import { mapGetters } from 'vuex'
import { dbCryptosRef } from '../firebaseConfig'
export default {
data()
{
return {
symbol: this.$route.params.symbol,
crypto: {},
cryptoTest: {}
}
},
computed: {
...mapGetters ([
'getCryptos'
])
},
methods: {
getCrypto: function()
{
this.cryptoTest = dbCryptosRef.equalTo(this.$route.params.symbol)
}
},
created() {
this.getCrypto();
}
}
</script>
You need to call value to get the data
getCrypto: function() {
this.cryptoTest = dbCryptosRef.equalTo(this.$route.params.symbol).once('value').then(snapshot => {
// do what you want with snapshot data
})
}
You can read more in Firebase document

Resources