1

I have a simple div with a v-for loop that displays items on a page. These items have a class on them which I would like to select using Javascript's querySelector method.

<div class="product-feed">
  <div v-for="Product in ProductFeed" :key="Product.ProductID" class="product-item" >
    <Product-Vue-Component :Product="Product"></Product-Vue-Component>
  </div>
</div>

<script>
...
setup() {
  async function loadFeed(){
    await nextTick();
    let element1 = document.querySelector('.product-feed'); 
    console.log(`element1`, element1) // this works and displays the element

    let element2 = document.querySelector('.product-item:last-of-type'); 
    console.log(`element2`, element2) // this comes back as null
  }
}

  onMounted(()=> {
    loadFeed();
  })
}
...
</script>

Even though I am waiting for the DOM to render using nextTick(), the function loadFeed() cannot pick up on any item that is in the v-for loop.

I need to detect items in the v-for loop so that I can implement an infinite scroll feature where more items are loaded as the user scrolls to the bottom of the list of .product-item elements (hence :last-of-type pseudo selector)

Where is it going wrong and is it possible to select elements this way?

Nikola Pavicevic
  • 21,952
  • 9
  • 25
  • 46
volume one
  • 6,800
  • 13
  • 67
  • 146
  • 1
    Everything works in isolated example: https://jsfiddle.net/matvey_andreyev/4qgny59j/2/ Are you sure that your ProductFeed is available at the onMounted + nextTick time? – Matvey Andreyev Sep 30 '21 at 08:56
  • @MatveyAndreyev Thank you for the test, it must be a race issue then – volume one Sep 30 '21 at 09:27

3 Answers3

1

Try to set ref on div with class="product-item"

<div ref="el" v-for="Product in ProductFeed" :key="Product.ProductID" class="product-item" >

then in setup function :

const el = ref(null)

onMounted(() => {
    loadFeed()
  })

async function loadFeed(){
  await nextTick();
    let element1 = document.querySelector('.product-feed'); 
    console.log(`element1`, element1) // this works and displays the element

    console.log(el.value) 
  }
}
return {el}
Nikola Pavicevic
  • 21,952
  • 9
  • 25
  • 46
0

Please, use refs for that just add ref attribute to the container ref="productFeed" and get this element with

import { ref } from 'vue'
...    
const productFeed = ref(null)
...
return {
    productFeed
}

Then you can use productFeed.value as a variable, containing dom element

ZloiGoroh
  • 411
  • 4
  • 11
  • And for loops use [this](https://v3.vuejs.org/guide/composition-api-template-refs.html#usage-inside-v-for) – ZloiGoroh Sep 30 '21 at 07:47
  • I need `product-item` not `ProductFeed` – volume one Sep 30 '21 at 07:57
  • For that i've left a link for you write `:ref="el => { if (el) divs[i] = el }"` on your `product-item` element create a variable for your elements `const divs = ref([])`, clear it on update `onBeforeUpdate(() => { divs.value = [] })`, and use `console.log(divs.value)` as an array of domElements – ZloiGoroh Sep 30 '21 at 10:10
-1

Try to use refs like this:

<div
  v-for="Product in ProductFeed" :ref="`product--${Product.id}`">
</div>
tony19
  • 125,647
  • 18
  • 229
  • 307
Ihar Dziamidau
  • 337
  • 2
  • 9