Question
I'm trying to trigger [GA events](https://google-
analytics.nuxtjs.org/usage/event-tracking) using Nuxt. It's successfully
working but it's only returning the first one it runs into because of
document.querySelector
rather than querySelectorAll
. I have tried the
spread operator and a for()
but still no luck - the compiler just says
cannot read property txt of undefined
.
Here's my v-for:
<ul>
<li class="li-item" v-for="item in items" :key="item.id" @click="doGA" :data-txt="item.name">
{{ item.name }}
</li>
</ul>
<ListDetails
:items="[
{
name: 'Lorem',
},
{
name: 'Ipsum',
},
{
name: 'Dolor',
},
]"
/>
methods: {
doGA(){
this.$ga.event({
eventCategory: "Ext links",
eventAction: "click",
//this.dataset.txt does not work below here either
eventLabel: document.querySelectorAll('.li-item').dataset.txt;
});
}
}
So when a user clicks 'Ipsum' it's returning 'Lorem' in GA and likewise for
'Dolor' it will do the same. It is because I have used
document.querySelector
rather than selectorAll
as I have said above, but I
can't get all()
to work properly.
As we know querySelector
will return this first one the browser finds.
Answer
TLDR: querySelector
and querySelectorAll
are usually not the way to go in
VueJS, if you want to select something. Either bind with state or find it with
a this.$refs[...]
.
With a template looking like this
<ul ref="list">
<li v-for="item in items" :key="item.id" @click="doGA(item.name)">
{{ item.name }}
</li>
</ul>
You could call the method on each of your element like this
methods: {
doGA(itemName){
this.$ga.event({
eventCategory: "Ext links",
eventAction: "click",
eventLabel: itemName
})
}
}
Otherwise, if you want to send all of them, you can do the following
<template>
<ul>
<li v-for="item in items" :key="item.id" @click="doGA">
<span :ref="`item-${item.id}`" :data-txt="`fancyText-${item.id}`">
number >> {{ item.id }}
</span>
</li>
<ul>
</template>
<script>
export default {
data() {
return {
items: [
{
id: 1,
name: 'Lorem',
},
{
id: 2,
name: 'Ipsum',
},
{
id: 3,
name: 'Dolor',
},
],
}
},
methods: {
async doGA() {
for (const item of this.items) {
console.log('element found', this.$refs[`item-${item.id}`][0].dataset.txt)
await this.$ga.event({
eventCategory: 'Ext links',
eventAction: 'click',
eventLabel: this.$refs[`item-${item.id}`][0].dataset.txt,
})
}
},
},
}
</script>
Notes
- $refs is the way to go in VueJS, rather than
querySelector
. async/await
may be useful if you do care about the order, if you don't and only want to send them, I guess that you can pass on this one.- You can remove the
span
s, I let it for visibility mainly. - I used
data
here, but this should behave pretty much the same with any props.