New to Vue, JS and Firebase been taking tutorials for weeks and now trying to build a test project. Embarrassed to say I have been stuck on this particular problem for several days. Trying to write this question as best I can given my current level of understanding which is pretty basic.
Desired Outcome: What I am trying to do is query firebase database to get the last event created by current user so that, if it exists, I can then pre-fill some of the Vue form data when they create their next entry.
Sounds simple enough but my tutorials only cover single document retrieval/display when you already have the document id, OR, how to retrieve and display all documents from a collection in a list. My need is hybrid in that don't know the document ID until I query to get it and every attempt to combine the functionality from tutorials has failed...multiple times.
Currently, I am able to query the DB just fine and can verify it returns the results I want to an object which I can log to the console and 'see', but, can't for the life of me figure out how to get to the data within that object once back on the doc template.
JS Code (getLastEvent-SO.js)
import { ref } from 'vue'
import { db } from '@/firebase/config'
import { collection, getDocs, query, where, orderBy, limit } from 'firebase/firestore'
const getLastEvent = (u) => { // u = user id
const lastEvent = ref([])
let collectionRef = collection(db, 'events') // establish reference
collectionRef = query(collectionRef, where("userId", "==", u ), orderBy("created", "desc"), limit(1)) // should return last event if exists
getDocs(collectionRef)
.then(snapshot => {
let docs = []
let eId = null
snapshot.docs.forEach(doc => { // using a loop because I couldnt figure out how to get a single doc without first having the id of that doc which I don't know until I query to get users last event created
docs.push({ ...doc.data(), id: doc.id })
})
lastEvent.value = docs // assign value of docs to lastEvent
})
console.log('lastEvent1:', lastEvent) // console display proves the record stored is the one I want but how do I access/print to console the values?
return { lastEvent }
}
export default getLastEvent
Vue Code:
<template>
<form @submit.prevent="handleSubmit">
<h2>New event</h2>
<p v-if="lastEvent">Last Start Date: {{ lastEvent.startDate }} </p> <!-- PROBLEM: this will NOT display - why??? -->
...more form inputs...
<button>Add event</button>
</form>
</template>
<script>
import getUser from "@/composables/getUser";
import getLastEvent from "@/composables/getLastEvent-SO";
export default {
setup() {
// Query last user event created so default form values based on last entry can be set
const { user } = getUser();
const { lastEvent } = getLastEvent(user.value.uid)
return { lastEvent };
},
};
</script>
Copied from Chrome/console (lastEvent):
{
"__v_isShallow": false,
"dep": {
"w": 0,
"n": 0
},
"__v_isRef": true,
"_rawValue": [
{
"userId": "H0jZIKGTggeX4DsjucGR50Cb8663",
"reservation": "",
"startDate": "2022-07-07",
"created": 1656595528420,
"location": "mpmCHrVYDK9icr3yTnYG",
"startTime": "09:00a",
"type": "Open",
"duration": 1,
"id": "ZHnbrLWkYO9gHdjKiygk"
}
],
"_value": [
{
"userId": "H0jZIKGTggeX4DsjucGR50Cb8663",
"reservation": "",
"startDate": "2022-07-07",
"created": 1656595528420,
"location": "mpmCHrVYDK9icr3yTnYG",
"startTime": "09:00a",
"type": "Open",
"duration": 1,
"id": "ZHnbrLWkYO9gHdjKiygk"
}
]
}
Any hint as to why I am unable to access the data from within the document template as {{ lastEvent.startDate }} ??
[edit: added this screen-shot of the console where I copied the object from by request]
CodePudding user response:
Aside from getLastEvent being asynchronous (make sure you await your database call before returning lastEvent), what you're returning from the function is an array, while in your Vue file you're using it as if it's an object. Either set lastEvent.value equal to desired element in your array (preferred)
const snapshot = await getDocs(collectionRef);
...
lastEvent.value = docs[0]; // assign value of docs to lastEvent
or in your Vue file you can call (though you still need to make your function asynchronous):
<p v-if="lastEvent">Last Start Date: {{ lastEvent[0].startDate }}</p>