I am attempting to build a Vue.js component that enables deleting of nested Firebase data. My component currently looks like the following:
<v-flex v-for="user in users" :key="user.id" xs12 md12>
<v-layout row wrap>
<v-flex v-for="newUser in user.gallery" :key="newUser.id" xs12 sm6 md3>
<v-img :src="newUser.image" />
<v-btn @click="deleteImg(newUser.id)">x</v-btn>
</v-flex>
</v-layout>
</v-flex>
This component uses a v-for directive to first loop through all Firebase items returned to the users
array. The second v-for directive loops through all of the images inside a nested Firebase array called gallery
. The delete button is intended to target the id of each image (newUser.id) inside the nested gallery
array. Here is the deleteImg()
method:
deleteImg (img) {
db.collection('users').doc(img).delete()
}
When I click the deleteImg()
button, I get the following handler error:
Function CollectionReference.doc() requires its first argument to be of type non-empty string, but it was: undefined
How can I adjust the deleteImg()
handler to properly target images based on id in the nested array? Thanks!
******REVISION******
Here is the full code for a better example of what I am trying to accomplish. Basically, this component is set up to push new input into an array called events
(which already exists as a document field in Firebase), and then then return those array items in user.events
to the screen. As you can see in the screenshot below, those inputted items are stored in the events array. Those array items render on the screen just fine. I am attempting to delete those array items, but am not sure how to properly target them. How can I configure the deleteInput()
method to target those array items?
<template>
<div class="input">
<input v-model="newInput" />
<button @click.prevent="addInput()">submit</button>
<br><br>
<div v-for="user in users" :key="user.id">
<div v-for="newUser in user.events" :key="newUser.id">
<h3>{{ newUser.name }}</h3>
<button @click="deleteInput(newUser.id)">x</button>
</div>
</div>
</div>
</template>
<script>
import firebase from 'firebase'
import { db } from '@/main'
export default {
name: 'HelloWorld',
data: () => ({
newInput: null,
users: []
}),
mounted () {
this.getData()
},
methods: {
async getData () {
let snapshot = await db.collection('users').get()
const users = []
snapshot.forEach(doc => {
let appData = doc.data()
appData.id = doc.id
users.push(appData)
})
this.users = users
},
async addInput () {
let finalInput = this.newInput
let querySnapshot = await db.collection('users').where('user_id', '==', firebase.auth().currentUser.uid).get()
querySnapshot.forEach(function(doc) {
doc.ref.update({'events': firebase.firestore.FieldValue.arrayUnion({
'name': finalInput
})
})
})
this.newInput = ''
this.getData()
},
deleteInput (item) {
db.collection('users').doc(item).delete()
}
}
}
</script>
There are two pieces of code in your question (somehow two linked but different questions): an initial one and one after the REVISION.
Let's first give the answer for the initial question: with your Vue.js component code you need to have a users
array that looks like:
users: [
{
id: 1,
gallery: [
{ id: 11, image: "http://...image1.jpg" },
{ id: 12, image: "http://...image2.jpg" },
{ id: 13, image: "http://...image3.jpg" }
]
},
{
id: 2,
gallery: [
{ id: 21, image: "http://...image1.jpg" },
{ id: 22, image: "http://...image2.jpg" },
{ id: 23, image: "http://...image3.jpg" }
]
}
]
It means you have to "construct" your Firestore documents in such a way they return an array with this format.
For the second problem (after the REVISION sub-title):
You should use the optional second argument of v-for
to get the index of the current item and call the deleteInput()
with this index
value plus the user.id
, as follows:
<div v-for="user in users" :key="user.id">
<div v-for="(newUser, index) in user.events" :key="newUser.id">
<h3>{{ newUser.name }}</h3>
<button @click="deleteInput(user.id, index)">x</button>
</div>
</div>
Then in deleteInput()
you need to
either
overwrite the events
array for the user
(with id == user.id) with a new events
array, in which you have deleted the element at position index
,
or
use the arrayRemove()
method with the entire object (events, email, name, etc...).
I would opt for the first approach.
Note that depending on your exact use case you may have to do that in a transaction, to be sure the events
array was not modified between the initial read and the modifciation.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.