vuejs3primevue

usage of ref in vue3


I wrote a vue3 component which uses the VirtualScroller from PrimeVue and I would like to scroll to the end of the scroller each time I'm adding new elements. For that, there is scrollInView method which is defined on the component and documented here

My code looks like this (it's typescript with vue-class-component and single file syntax):

<template>
 ...
   <VirtualScroller :items="content" :itemSize="50" class="streamscroller" ref="streamscroller">
      <template v-slot:item="{ item }">
        <pre>{{ item }}</pre>
      </template>
    </VirtualScroller>
...
</template>

<script lang="ts">
...
import { ref, ComponentPublicInstance } from "vue";
import VirtualScroller from "primevue/virtualscroller";
...
@Options({
  components: {
    VirtualScroller,
...
  },
})
export default class StreamResultViewer extends Vue {
  streamscroller = ref<ComponentPublicInstance<VirtualScroller>>();
  content: string [] = [ "No output" ];
...
  mounted(): void {
...
    console.debug("scroller mounted: ", this.streamscroller.value);   // <=== here, already the value is indefined
  }
  onData(msg: string): void {
      const lines = msg.split('\n');
      const content =  [...this.content, ...lines];
      this.content = content;
      console.debug("scroller: ", this.streamscroller.value);   // <== always undefined
      this.streamscroller.value?.scrollInView(this.content.length, 'to-end', 'smooth');   // <== so never called
  }
...

The virtual scroller works well (I can add lines each time they arrives and the scroll bar moves...) but I can never call the scroll method because the ref is undefined...

I'd be very grateful for any clue...

Thank you


Solution

  • The only workaround I found is too use $refs like this:

    onData(msg: string): void {
      const lines = msg.split('\n');
      const content = [...this.content, ...lines];
      this.content = content;
      const scroller = this.$refs.streamscroller as VirtualScroller;
      scroller.scrollInView(this.content.length, 'to-end', 'smooth');
    }
    

    This way, I am able to call the scrolling method and it works fine.

    If someone can explain how it should work normally with ref<T>() in the vue-class-component + typescript mode, I'd be glad to hear that.